从sqlalchemy获取关系元数据

时间:2012-11-05 14:29:14

标签: python orm sqlalchemy metadata

我有一个非常简单的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来编辑对象User(以及其他类型的类)。所以我需要获取表格的所有元数据,例如,我可以这样做:

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

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

1 个答案:

答案 0 :(得分:2)

确实没有现成的。经过一些逆向工程后,我不得不提出自己的功能。

这是我使用的元数据。我与你正在寻找的东西差别不大,但也许你可以使用它。

# 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)

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