你如何@rpc _returns spyne 中的多态类型?

How do you @rpc _returns polymorphic types in spyne?

编辑

示例,

class A(ComplexModel):
    Id = Unicode

class B(ComplexModel):
    __extends__ = A
    Name = Unicode

@rpc(String, _returns=A)
def hello(self, name):
    ret = B()
    B.Id = '123'
    B.Name = name
    return ret

您如何处理这种行为,使其 return 不是 A 的对象?


我如何将 spyne 装饰器正确地写成 return 不止一种类型?例如,如果 _returns 设置为 ZObj,那么 returning 一个 XAccount(就像在代码中一样)不会做任何事情。

我可以编写 XAccount 对象,使其扩展 ZObj 并且是有效的 return 类型吗?

@rpc(String, _returns=(ZObj, XAccount))
def hello(self, name):
    acc = XAccount(
        user_name = name.upper(),
        first_name = name,
        last_name = 'last ' + name
    )
    return acc

Class 例子....

class ZObj(ComplexModel):
    id = Unicode(pattern='[a-zA-Z0-9]{32}|\d+')

class Account(DeclarativeBase):
    __tablename__ = 'account'

    id = Column(Integer, primary_key=True)
    user_name = Column(String(256))
    first_name = Column(String(256))
    last_name = Column(String(256))


class XAccount(TableModel):
    __table__ = Account.__table__

删除我之前的回答,因为您显然需要多态性,而不是多种 return 类型。

因此,在 Spyne 中有两种实现多态性的方法:Python 方法和 Spyne 方法。

设:

class A(ComplexModel):
    i = Integer

class B(A):
    s = Unicode

class C(A):
    d = DateTime

Python 方法使用鸭子输入 return 值。

让我们定义一个泛型 class:

class GenericA(ComplexModel):
    i = Integer
    s = Unicode
    d = DateTime

并将其用作示例服务的 return 值:

class SomeService(ServiceBase):
    @rpc(Unicode(values=['A', 'B', 'C']), _returns=GenericA)
    def get_some_a(self, type_name):
        # (...)

通过这种方式,您可以获得数据,但它被标记为 GenericA 对象。如果您不关心这个,您可以创建一个 class ,它具有所有对象的所有类型(假设具有相同名称的属性具有相同的类型)并完成它。这很简单,稳定并且今天可以使用。

如果这还不能满足您的需要,您必须按照 Spyne 的方式进行多态性处理。为此,首先将 return 类型设置为基础 class:

class SomeService(ServiceBase):
    @rpc(Unicode(values=['A', 'B', 'C']), _returns=A)
    def get_some_a(self, type_name):
        # (...)

并将您的输出协议标记为多态的:

application = Application([SomeService], 'tns',
    in_protocol=Soap11(validator='lxml'),
    out_protocol=Soap11(polymorphic=True)
)

这至少需要 Spyne-2.12。

工作示例:https://github.com/arskom/spyne/blob/a1b3593f3754a9c8a6787c29ff50f591db89fd49/examples/xml/polymorphism.py

此外,您不需要这样做:

class Account(DeclarativeBase):
    __tablename__ = 'account'

    id = Column(Integer, primary_key=True)
    user_name = Column(String(256))
    first_name = Column(String(256))
    last_name = Column(String(256))

class XAccount(TableModel):
    __table__ = Account.__table__

这同样有效:

from spyne import TTableModel

TableModel = TTableModel() # Think of this as Spyne's declarative_base

class Account(TableModel):
    __tablename__ = 'account'

    id = Integer(primary_key=True)
    user_name = Unicode(256)
    first_name = Unicode(256)
    last_name = Unicode(256)

您的 table 元数据在 TableModel.Attributes.sqla_metadata

中的位置

以这种方式创建的对象可用于 SQLAlchemy 查询和 Spyne 类型。