你怎么样@rpc _returns spyne中的多态类型?

时间:2015-07-13 21:19:38

标签: python soap 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

如何处理此行为,因此它不会返回A的对象?

如何编写spyne装饰器以正确返回多种类型?例如,如果_returns设置为ZObj,则返回XAccount(如代码中所示)不会执行任何操作。

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

@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 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__

2 个答案:

答案 0 :(得分:1)

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

所以,在Spyne中有两种做多态的方法:Python方式和Spyne方式。

让:

class A(ComplexModel):
    i = Integer

class B(A):
    s = Unicode

class C(A):
    d = DateTime

Python方法使用duck typing来返回值。

让我们定义一个泛型类:

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

并将其用作我们的示例服务的返回值:

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

这样,您可以获取数据,但它被标记为GenericA个对象。如果你不关心这个,你可以创建一个包含所有对象的所有类型的类(假设具有相同名称的属性具有相同的类型),并且只需要完成它。这很简单,稳定,现在可以使用。

如果这不足以满足您的需求,您必须以Spyne的方式进行多态性。为此,首先将返回类型设置为基类:

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

答案 1 :(得分:0)

此外,您不需要这样做:

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)

您的表元数据位于TableModel.Attributes.sqla_metadata

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