具有动态名称的Django模型字段

2024-06-16 18:10:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我想通过一个通用的mixin或抽象模型向现有模型添加新的CharFields,但这些字段的名称取决于configuraton。因此,一个模型将有someprefix1_title字段和另一个模型someprefix2_title。在

是否有可能使这种方法发挥作用:

class AbstractModel(models.Model):
    self.fields_prefix + '_title' = models.CharField(max_length=255, blank=True, default='')

    class Meta:
        abstract = True

class ModelOne(AbstractModel):
    fields_prefix = 'someprefix1'
    id = models.AutoField(primary_key=True)

class ModelTwo(AbstractModel):
    fields_prefix = 'someprefix2'
    id = models.AutoField(primary_key=True)

所以ModelOne可以有字段id和someprefix1\u title。在

upd:用add_to_class()进行monkey修补怎么样?它能工作吗?还是它是一个反模式,不应该使用?在


Tags: key模型idtruefieldsprefixtitlemodels
3条回答

最干净的方法可能是使用add_to_class()

ModelOne.add_to_class(
    '%s_title' % field_prefix, 
    models.CharField(max_length=255, blank=True, default='')
)

尽管如此,这仍然可以被认为是“猴子补丁”的所有缺点,如使应用程序更难维护,代码更难理解等。。。Bu如果您的用例确实需要这样做,那么它可能是最好的解决方案,因为add_to_class()是Django本身提供的一些功能,并且已经稳定了相当长一段时间。在

尝试使用工厂模式设置AbstractModel的不同版本。在

使用这种方法,您可以更严格地控制通过工厂函数dynamic_fieldname_model_factory修改{}的方式。在

我们也不会在ModelOne或{}之后修改它们的定义——其他解决方案已经指出这有助于避免可维护性问题。在

在模型.py公司名称:

from django.db import models


def dynamic_fieldname_model_factory(fields_prefix):
    class AbstractModel(models.Model):

        class Meta:
            abstract = True

    AbstractModel.add_to_class(
        fields_prefix + '_title',
        models.CharField(max_length=255, blank=True, default=''),
    )
    return AbstractModel


class ModelOne(dynamic_fieldname_model_factory('someprefix1')):
    id = models.AutoField(primary_key=True)


class ModelTwo(dynamic_fieldname_model_factory('someprefix2')):
    id = models.AutoField(primary_key=True)

以下是此代码生成的迁移:

^{pr2}$

Django模型可以用动态字段名创建。下面是一个简单的Django模型:

class Animal(models.Model):
    name = models.CharField(max_length=32)

下面是使用type()构建的等效类:

^{pr2}$

任何可以以正常方式定义的Django模型都可以使用type()生成。在

跑m南部有一组可靠的函数,用于处理Django项目的模式和数据库迁移。什么时候? 在开发中,South可以建议迁移,但不尝试自动应用它们

from south.db import db
model_class = generate_my_model_class()
fields = [(f.name, f) for f in model_class._meta.local_fields]
table_name = model_class._meta.db_table
db.create_table(table_name, fields)
# some fields (eg GeoDjango) require additional SQL to be executed
db.execute_deferred_sql()

相关问题 更多 >