使用元类设置时,Django迁移会忽略db_table

时间:2018-06-30 13:12:48

标签: python django migration metaclass dbtable

我正在使用一个元类来自动将我的Django模型数据库表名称从驼峰式设置为'_'分隔的名称,例如MyGreatModel的表名将类似于appname_my_great_model,而不是默认的appname_mygreatmodel

class PrettyModelBase(ModelBase):

    def __new__(cls, name, bases, attrs):
        super_new = ModelBase.__new__(cls, name, bases, attrs)
        module_name = camel_to_underscore(name)
        model_module = sys.modules[cls.__module__]

        app_label = super_new.__module__.split('.')[-2]
        db_table = '%s_%s' % (app_label, module_name)
        if not getattr(super_new._meta, 'proxy', False):
             super_new._meta.db_table = db_table

        return super_new


class BaseModel(models.Model):

    __metaclass__ = PrettyModelBase

    class Meta:
        abstract = True

class MyGreatModel(BaseModel):
    somefield = models.TextField(default="")

但是,迁移似乎并没有使用这个db_table名称。如果我运行makemigrations,则CreateModel在此模型的db_table中不会显示options。如果我将其硬编码在class Meta的{​​{1}}中,则可以。此外,如果我检查要与MyGreatModel一起运行的SQL,那么它表明它将创建python manage.py sqlmigrate...表,而不是带分隔符的表名。

但是,如果我运行此迁移,然后在Django shell中检查模型,那么appname_mygreatmodel会显示MyGreatModel._meta.db_table,正如我期望从我的元类中看到的那样。如果我为CreateModel手动添加my_great_model属性0001的init迁移选项,那么以后的迁移也都可以,但是Django应该自动执行此操作...

为什么Django迁移没有在这里使用db_table

我正在使用db_table

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

这个问题在django-developers邮件列表中重新提出:https://groups.google.com/forum/#!msg/django-developers/ncMCwMF2J3g/V3guuDbJCwAJ

Django迁移使用model._meta.original_attrs来确定元类的定义:https://github.com/django/django/blob/stable/2.2.x/django/db/migrations/state.py#L454

因此,如果您要动态更改创建后的model._meta,则还需要相应地更改其original_attrs字典。我认为这应该有效(未试用)。