在我的应用程序中,我有一个模型,我只在运行时知道它的列数。使用Factory如下函数创建模型可以很好地解决这个问题。但是,如果我多次使用它(可能有不同的字段),外键的创建ref会引发异常:
AttributeError: Foreign key: dynamictable.ref related name "dynamictable_set"
collision with foreign key using same related_name.
Run Code Online (Sandbox Code Playgroud)
该消息非常清楚,当我related_name在创建外键时设置参数时没有错误。
问题:
为什么我不能related_name第二次使用相同的?我也需要重新定义StaticTable吗?
有没有更好的方法来使用动态模型写入多个数据库?
最小的、可重现的例子:
import peewee
database_proxy = peewee.Proxy()
class BaseModel(peewee.Model):
class Meta:
database = database_proxy
class StaticTable(BaseModel):
foo = peewee.DoubleField()
def Factory(fields):
class DynamicTable(BaseModel):
ref = peewee.ForeignKeyField(StaticTable)
for field in fields:
peewee.DoubleField().add_to_class(DynamicTable, field)
return DynamicTable
def Test(fname, fields):
db = peewee.SqliteDatabase(fname)
database_proxy.initialize(db)
db.create_table(StaticTable)
dyntable = Factory(fields)
db.create_table(dyntable)
db.close()
Test(':memory:', ['foo', 'bar'])
Test(':memory:', ['foo', 'bar', 'extra'])
Run Code Online (Sandbox Code Playgroud)
我认为这突出了 peewee 中的一个错误,您可能明确希望忽略任何反向引用。我已经打开了一张票,并将解决它。
https://github.com/coleifer/peewee/issues/465
同时,您可以通过在模型上设置动态相关名称来消除错误,例如
def Factory(fields):
dynamic_name = '_'.join(fields)
class DynamicTable(BaseModel):
ref = peewee.ForeignKeyField(StaticTable, related_name=dynamic_name)
for field in fields:
peewee.DoubleField().add_to_class(DynamicTable, field)
return DynamicTable
Run Code Online (Sandbox Code Playgroud)
更新:根据 #465 中的修复,现在可以禁用 backref 验证:
def Factory(fields):
class DynamicTable(BaseModel):
ref = peewee.ForeignKeyField(StaticTable, related_name=dynamic_name)
class Meta:
validate_backrefs = False
for field in fields:
peewee.DoubleField().add_to_class(DynamicTable, field)
return DynamicTable
Run Code Online (Sandbox Code Playgroud)