Django dynamic model fields

Я работаю над многопользовательским приложением, в котором некоторые пользователи могут определять свои собственные поля данных (через администратора) для сбора дополнительных данных в формах и отчетов по этим данным. Последнее обстоятельство делает 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 к Site - каждый сайт будет иметь свой набор пользовательских полей данных, но использовать одну и ту же базу данных. Затем различные конкретные поля данных могут быть определены следующим образом:

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'),)

Это приводит к следующему использованию:

custom_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, как указано выше, так как он не будет хорошо работать с запросами.
156
задан Ivan Kharlamov 21 December 2011 в 20:39
поделиться