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