【发布时间】:2018-12-20 03:23:31
【问题描述】:
我想根据单位字段动态生成一个类,如下所示:
def gm_a(unit):
tname = '%s_a' % unit
for c in db.Model._decl_class_registry.values():
if hasattr(c, '__table__') and c.__table__.fullname == tname:
return c
class A(DynamicBase):
__tablename__ = '%s_a' % unit
id = db.Column(db.Integer, primary_key=True)
......# other fields
return A
你可以看看我是要在ORM操作中使用table_a还是desk_a表,我可以这样做:
@app.route('/<unit>/a')
def a(unit):
obj_table = gm_a('table').query.filter_by(xxx).all()
obj_desk = gm_a('desk').query.filter_by(xxx).all()
这样,我们就可以对同结构的不同表名的表进行操作了。有个问题,如果我们有3个gm_*函数(gm_a,gm_b,gm_c)和3个路由(/<unit>/a,/<unit>/b,/<unit>/c),每个模板是这样的:
<ul>
<li><a href="a">A</a></li>
<li><a href="b">B</a></li>
<li><a href="c">C</a></li>
</ul>
如果我们随机点击这些链接,我们希望在 db.Model._decl_class_registry.values() 中生成 3 个类,在 db.metadata.tables 中生成 3 个表。
---
[<class '__main__.gm_a.<locals>.A'>, <class '__main__.gm_b.<locals>.B'>, <class '__main__.gm_c.<locals>.C'>]
immutabledict({'table_a': Table('table_a', MetaData(bind=None), Column('id', Integer(), table=<table_a>, primary_key=True, nullable=False), schema=None), 'table_b': Table('table_b', MetaData(bind=None), Column('id', Integer(), table=<table_b>, primary_key=True, nullable=False), schema=None), 'table_c': Table('table_c', MetaData(bind=None), Column('id', Integer(), table=<table_c>, primary_key=True, nullable=False), schema=None)})
127.0.0.1 - - [12/Jul/2018 09:58:03] "GET /table/b HTTP/1.1" 200 -
---
[<class '__main__.gm_a.<locals>.A'>, <class '__main__.gm_b.<locals>.B'>, <class '__main__.gm_c.<locals>.C'>]
immutabledict({'table_a': Table('table_a', MetaData(bind=None), Column('id', Integer(), table=<table_a>, primary_key=True, nullable=False), schema=None), 'table_b': Table('table_b', MetaData(bind=None), Column('id', Integer(), table=<table_b>, primary_key=True, nullable=False), schema=None), 'table_c': Table('table_c', MetaData(bind=None), Column('id', Integer(), table=<table_c>, primary_key=True, nullable=False), schema=None)})
127.0.0.1 - - [12/Jul/2018 09:58:04] "GET /table/c HTTP/1.1" 200 -
---
[<class '__main__.gm_a.<locals>.A'>, <class '__main__.gm_b.<locals>.B'>]
immutabledict({'table_a': Table('table_a', MetaData(bind=None), Column('id', Integer(), table=<table_a>, primary_key=True, nullable=False), schema=None), 'table_b': Table('table_b', MetaData(bind=None), Column('id', Integer(), table=<table_b>, primary_key=True, nullable=False), schema=None), 'table_c': Table('table_c', MetaData(bind=None), Column('id', Integer(), table=<table_c>, primary_key=True, nullable=False), schema=None)})
127.0.0.1 - - [12/Jul/2018 09:58:04] "GET /table/b HTTP/1.1" 200 -
---
[<class '__main__.gm_a.<locals>.A'>, <class '__main__.gm_b.<locals>.B'>]
immutabledict({'table_a': Table('table_a', MetaData(bind=None), Column('id', Integer(), table=<table_a>, primary_key=True, nullable=False), schema=None), 'table_b': Table('table_b', MetaData(bind=None), Column('id', Integer(), table=<table_b>, primary_key=True, nullable=False), schema=None), 'table_c': Table('table_c', MetaData(bind=None), Column('id', Integer(), table=<table_c>, primary_key=True, nullable=False), schema=None)})
127.0.0.1 - - [12/Jul/2018 09:58:04] "GET /table/a HTTP/1.1" 200 -
正如你在图片或代码中看到的,我们之前已经点击了a,b,c,所以class和table中有三个。但是一旦我们点击 b,.vales() 中就只有 a, b。由于没有table_c类,所以在我们的程序逻辑中会重新生成,但是Tables中确实存在table_c。所以会抛出异常:
sqlalchemy.exc.InvalidRequestError: Table 'table_c' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object.
我很困惑为什么 db.Model._decl_class_registry.values() 中的数字会随机变化,而 _decl_class_registry.values() 和 db.metadata.tables() 的数字会不同。我也用sqlalchemy-utils中的get_class_by_table函数,但是原理和我们的方法一致,不起作用。
有人知道为什么吗?谢谢。
【问题讨论】:
标签: python-3.x flask sqlalchemy flask-sqlalchemy