1

私は非常に単純な 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))

オブジェクト User (および他のタイプのクラス) を編集するための 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 に関連するテーブルを表示するだけです。私の質問が明確でない場合はお知らせください

4

1 に答える 1

2

It's true that is not readily available. I had to come up with my own function after some reverse-engineering.

Here is the metadata that I use. I little different than what you are are looking for, but perhaps you can use it.

# 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

But it doesn't have the primary key. I use a separate function for that.

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

Perhaps I should put the primary key name in the metadata.

于 2012-11-05T14:48:57.770 に答える