【问题标题】:Combining __table_args__ with constraints from mixin classes in SQLAlchemy将 __table_args__ 与 SQLAlchemy 中 mixin 类的约束相结合
【发布时间】:2014-06-18 09:36:02
【问题描述】:

在 SQLAlchemy 中,我已经阅读了如何在声明声明时结合来自不同 mixin 的 __table_args__

Combining Table/Mapper Arguments from Multiple Mixins

我的问题是,该示例显示了如何在链的末端(MRO 中的最终类)完成此操作,但是如果我有这些 Mixin 并希望它发生在MyClientMixinBase 类以避免将此代码复制到其他类型的 mixins?

class LaneCarrierCommitmentSummaryMixin(object):
    """ Lane Carrier Commitment Summary.

    A base class for LCCS to mixin with a client specific class.
    """

    __tablename__ = 'lane_carrier_commitment_summary'
    __table_args__ = ((UniqueConstraint(['hashmap_key', 'bow'],
                                        name='uq_lane_carrier_commitment_summary_hashmap_key_bow')),)

class MyClientMixin(object):
    """ MyClient Mixin class for providing the ETL schema. """

    __table_args__ = {'schema': 'myclient_etl'}

class MyClientLaneCarrierCommitmentSummary(LaneCarrierCommitmentSummaryMixin, DateTrackedMixin, MyClientMixin, Base):
    pass

我在这个概念上有点挣扎。

【问题讨论】:

    标签: python orm sqlalchemy declarative


    【解决方案1】:

    这个基类会搜索所有的 mixin 来添加 __table_args__,然后检查当前类中的 __local_table_args__ 来添加。这样,__local_table_args__ 不会与声明的 attr 冲突。基类 (cls.mro()) 以相反的顺序进行检查,这样链中较低的 mixin 会被较高的 mixins 覆盖。

    def _process_args(cls, attr, out_args, out_kwargs):
        try:
            args = getattr(cls, attr)
        except AttributeError:
            return
    
        if isinstance(args, Mapping):  # it's a dictionary
            out_kwargs.update(args)
        else:  # it's a list
            if isinstance(args[-1], Mapping):  # it has a dictionary at the end
                out_kwargs.update(args.pop())
    
            out_args.extend(args)
    
    class Base():
        @declared_attr
        def __mapper_args__(cls):
            args = []
            kwargs = {}
    
            for mixin in reversed(cls.mro()):
                _process_args(mixin, '__mapper_args__', args, kwargs)
    
            _process_args(mixin, '__local_mapper_args__', args, kwargs)
    
            return kwargs  # mapper only takes dict
    
        @declared_attr
        def __table_args__(cls):
            args = []
            kwargs = {}
    
            for mixin in reversed(cls.mro()):
                _process_args(mixin, '__table_args__', args, kwargs)
    
            _process_args(cls, '__local_table_args__', args, kwargs)
    
            args.append(kwargs)  # [item, item, ...,  kwargs]
            return tuple(args)
    

    你所有的 mixin 都应该像往常一样定义 __table_args__,但是从 Base 继承的“真实”类应该定义 __local_table_args__

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 1970-01-01
      相关资源
      最近更新 更多