首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >peewee:重用动态创建的模型

peewee:重用动态创建的模型
EN

Stack Overflow用户
提问于 2014-11-18 17:25:43
回答 2查看 1.2K关注 0票数 3

在我的应用程序中,我有一个只有在运行时才知道列数的模型。使用下面的Factory这样的函数来创建模型很好地解决了这个问题。但是,如果我多次使用它(可能有不同的字段),创建外键ref会抛出一个异常:

代码语言:javascript
复制
AttributeError: Foreign key: dynamictable.ref related name "dynamictable_set" 
collision with foreign key using same related_name.

消息非常清楚,当我在创建外键时设置related_name参数时,没有错误。

问题

  1. 为什么我不能第二次使用相同的related_name?我也需要重新定义StaticTable吗?
  2. 是否有更好的方法可以用动态模型写入多个数据库?

最小的、可复制的示例:

代码语言:javascript
复制
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'])
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-11-18 23:28:30

我认为这突出了peewee中的一个bug,您可能明确地想忽略任何回退。我已经开了一张票,我会解决的。

https://github.com/coleifer/peewee/issues/465

同时,您可以通过在模型上设置一个动态related_name来消除错误。

代码语言:javascript
复制
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

更新:根据#465中的修复程序,现在可以禁用backref验证:

代码语言:javascript
复制
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
票数 5
EN

Stack Overflow用户

发布于 2014-11-19 09:58:16

@coleifer的建议(在他的回答中)很有效,只要字段列表是唯一的。由于在我的例子中不能保证这一点,所以我想出了一个稍微复杂一些的解决方案,其中所有的模型类都是在工厂中创建的:

代码语言:javascript
复制
import peewee

database_proxy = peewee.Proxy()

def orm_factory():

    class OrmWrapper:
        class BaseModel(peewee.Model):
            class Meta:
                database = database_proxy

        class StaticTable(BaseModel):
            foo = peewee.DoubleField()

        @classmethod
        def dyntable_factory(cls,fields):
            class DynamicTable(cls.BaseModel):
                ref = peewee.ForeignKeyField(cls.StaticTable)
            for field in fields:
                peewee.DoubleField().add_to_class(DynamicTable, field)
            return DynamicTable

    return OrmWrapper

def test(fname, fields):
    orm = orm_factory()
    db = peewee.SqliteDatabase(fname)
    database_proxy.initialize(db)
    db.create_table(orm.StaticTable)
    dyntable = orm.dyntable_factory(fields)
    db.create_table(dyntable)
    db.close()

test(':memory:', ['foo', 'bar'])
test(':memory:', ['foo', 'bar'])
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27000279

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档