Django动态模型字段

这几天准备写个工作流系统,因为工作流中一些模板的字段都是不固定的,于是思考有没有动态的模型字段,刚好找到了某个大神写的东西,觉得有用(还没有实践),于是记录一下。

原文地址: https://stackoverflow.com/questions/7933596/django-dynamic-model-fields
翻译地址:http://stackoverflow.org.cn/front/ask/view?ask_id=17340
我正在开发一个多租户应用程序,其中一些用户可以通过管理员定义自己的数据字段,以收集表单中的其他数据并报告数据。 后一位使JSONField不是一个很好的选择,所以我有以下解决方案:

class CustomDataField(models.Model):
    """
    Abstract specification for arbitrary data fields.
    Not used for holding data itself, but metadata about the fields.
    """
    site = models.ForeignKey(Site, default=settings.SITE_ID)
    name = models.CharField(max_length=64)

    class Meta:
        abstract = True

class CustomDataValue(models.Model):
    """
    Abstract specification for arbitrary data.
    """
    value = models.CharField(max_length=1024)

    class Meta:
        abstract = True

注意CustomDataField如何具有一个ForeignKey到站点 - 每个站点将有一组不同的自定义数据字段,但使用相同的数据库。 然后可以将各具体数据字段定义为:

class UserCustomDataField(CustomDataField):
    pass

class UserCustomDataValue(CustomDataValue):
    custom_field = models.ForeignKey(UserCustomDataField)
    user = models.ForeignKey(User, related_name='custom_data')

    class Meta:
        unique_together=(('user','custom_field'),)

这有以下用途

tom_field = UserCustomDataField.objects.create(name='zodiac', site=my_site) #probably created in the admin
user = User.objects.create(username='foo')
user_sign = UserCustomDataValue(custom_field=custom_field, user=user, data='Libra')
user.custom_data.add(user_sign) #actually, what does this even do?

但这感觉很笨重,特别是需要手动创建相关数据并将其与具体模型相关联。 有更好的方法吗?

已被抢先弃用的选项:

  • 自定义SQL即时修改表。 部分原因是因为这不会扩大,部分是因为它太多了。
  • 无数据解决方案,如NoSQL。 我没有反对他们,但他们还不是很好。 最终这些数据是打字的,并且存在使用第三方报告应用程序的可能性。
  • JSONField,如上所列,因为它不会很好地与查询。

原文有四个采纳答案,但我觉得只有一种更合适,下面只记录那一张答案。

JSONField:

JSON / JSONB字段支持任何JSON的可编码的数据类型,而不仅仅是键/值对,但也往往是更快(对于JSONB)比Hstore更紧凑。几个包实现JSON / JSONB字段,包括django-pgfields,但从Django 1.9,JSONField是一个内置的使用JSONB存储。
JSONField类似于HStoreField,并且可以使用大型字典执行得更好。它还支持除字符串以外的类型,例如整数,布尔和嵌套字典。

使用:

#app/models.py
from django.contrib.postgres.fields import JSONField
class Something(models.Model):
    name = models.CharField(max_length=32)
    data = JSONField(db_index=True)

在shell中创建:

>>> instance = Something.objects.create(
                 name='something',
                 data={'a': 1, 'b': 2, 'nested': {'c':3}}
           )

索引查询几乎与HStoreField相同,除了嵌套是可能的。 复杂索引可能需要手动创建(或脚本迁移)。

>> Something.objects.filter(data__a=1)
>>> Something.objects.filter(data__nested__c=3)
>>> Something.objects.filter(data__has_key='a')

感觉这个方法简单,可以试一下

你可能感兴趣的:(Django动态模型字段)