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