【问题标题】:Get the relationship metadata from sqlalchemy从 sqlalchemy 获取关系元数据
【发布时间】:2012-11-05 14:29:14
【问题描述】:

我有一个非常简单的 User 类定义:

class User(Base):
    implements(interfaces.IUser)
    __tablename__ = 'users'
    #Fields description
    id = Column(Integer, primary_key=True)

    client_id = Column(Integer, ForeignKey('w2_client.id'))
    client = relationship("Client", backref=backref('users', order_by=id))

我想自动生成一个 GUI 来编辑对象用户(和其他类型的类)。所以我需要获取表的所有元数据,例如我可以这样做:

    for c in User.__table__.columns:
        print c.name, c.type, c.nullable, c.primary_key, c.foreign_keys

但我无法获得有关“客户”关系的任何信息,c.foreign_keys 只显示与foreign_keys 相关的表,而不是我定义的属性“客户”。 如果我的问题不清楚,请告诉我

【问题讨论】:

    标签: python orm sqlalchemy metadata


    【解决方案1】:

    确实不容易获得。经过一些逆向工程后,我不得不提出自己的功能。

    这是我使用的元数据。我与您正在寻找的东西几乎没有什么不同,但也许您可以使用它。

    # structure returned by get_metadata function.
    MetaDataTuple = collections.namedtuple("MetaDataTuple",
            "coltype, colname, default, m2m, nullable, uselist, collection")
    
    
    def get_metadata_iterator(class_):
        for prop in class_mapper(class_).iterate_properties:
            name = prop.key
            if name.startswith("_") or name == "id" or name.endswith("_id"):
                continue
            md = _get_column_metadata(prop)
            if md is None:
                continue
            yield md
    
    
    def get_column_metadata(class_, colname):
        prop = class_mapper(class_).get_property(colname)
        md = _get_column_metadata(prop)
        if md is None:
            raise ValueError("Not a column name: %r." % (colname,))
        return md
    
    
    def _get_column_metadata(prop):
        name = prop.key
        m2m = False
        default = None
        nullable = None
        uselist = False
        collection = None
        proptype = type(prop)
        if proptype is ColumnProperty:
            coltype = type(prop.columns[0].type).__name__
            try:
                default = prop.columns[0].default
            except AttributeError:
                default = None
            else:
                if default is not None:
                    default = default.arg(None)
            nullable = prop.columns[0].nullable
        elif proptype is RelationshipProperty:
            coltype = RelationshipProperty.__name__
            m2m = prop.secondary is not None
            nullable = prop.local_side[0].nullable
            uselist = prop.uselist
            if prop.collection_class is not None:
                collection = type(prop.collection_class()).__name__
            else:
                collection = "list"
        else:
            return None
        return MetaDataTuple(coltype, str(name), default, m2m, nullable, uselist, collection)
    
    
    def get_metadata(class_):
        """Returns a list of MetaDataTuple structures.
        """
        return list(get_metadata_iterator(class_))
    
    
    def get_metadata_map(class_):
        rv = {}
        for metadata in get_metadata_iterator(class_):
            rv[metadata.colname] = metadata
        return rv
    

    但它没有主键。我为此使用了一个单独的函数。

    mapper = class_mapper(ORMClass)
    pkname = str(mapper.primary_key[0].name)
    

    也许我应该将主键名称放在元数据中。

    【讨论】:

    • 您刚刚确认没有干净的方法可以做到这一点。我现在的解决方案是使用一个定义我需要的所有信息的字典。感谢您的回答!
    猜你喜欢
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    • 2019-11-23
    • 1970-01-01
    • 2020-07-01
    • 2018-02-14
    • 1970-01-01
    相关资源
    最近更新 更多