#python #django #django-models
#python #django #django-модели
Вопрос:
Итак, у меня есть ситуация в Django, где у меня есть модель с именем S, которая может иметь ряд атрибутов, но в настоящее время я понятия не имею, какие атрибуты будут актуальными / обязательными. Чтобы справиться с этим, я подумываю о создании дополнительной модели SAttrib, которая имитирует словарную запись и обращается к ней через свойство метаданных. Смотрите ниже.
class S(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=128, blank=True, null=True)
description = models.CharField(max_length=128, blank=True, null=True)
created_date = models.DateTimeField(auto_now_add=True, auto_now=False)
modified_date = models.DateTimeField(auto_now_add=False, auto_now=True)
def __unicode__(self):
return smart_unicode(self.name)
class Meta:
db_table = "stest"
def _get_metadata(self):
class AD(dict):
def __init__(self, id):
self.id = id
def __getitem__(self, key):
return SampleAttrib.objects.filter(sample_id=self.id, attrib_key=key).get().attrib_value
return AD(self.id)
metadata = property(_get_metadata)
class SampleAttrib(models.Model):
s_id = models.ForeignKey("S")
attrib_key = models.CharField(max_length=128)
attrib_value = models.TextField()
class Meta:
db_table = 's_attrib'
unique_together = (('s_id', 'attrib_key'),)
Я хотел бы сделать так, чтобы у меня был доступ к атрибутам, хранящимся в SAttrib, путем реализации его как свойства. Поэтому я мог бы получить доступ к значениям следующим образом:
y = S.objects.get()
y.metadata["foo"]
Но тогда это становится беспорядком и требует много дополнительного кода для настройки и сохранения объектов / содержит и т.д.
s = S.objects.get()
s.metadata["foo"] = "spam"
.....
Есть ли лучший способ структурирования этого или чего-то, что уже есть в Django, чего мне не хватает?
Все предложения приветствуются….
Спасибо
Комментарии:
1. Если вы используете Django 1.8 и PostgreSQL, взгляните на HStoreField, это дает вам в значительной степени то, чего вы хотите достичь в рамках той же модели. docs.djangoproject.com/en/1.8/ref/contrib/postgres/fields /…
2. Я бы, вероятно, использовал просто вызываемое текстовое поле
metadata
и использовал json для сериализации / десериализации сохраненного dict. Если вам нужно запускать необработанные запросы к ключам / значениям, это не идеально, потому что только последняя версия mysql имеет функции для управления json. Не уверен насчет других движков БД.3. Я пытаюсь сделать это как можно более независимым от серверной части, но это определенно решает проблему, если я использую hstore в postgresql. Такая же проблема для json.
4. Я поддержал ваш ответ, однако ваше предложение, похоже, работает только с определенными версиями серверных баз данных / не переносимо широко
5. напротив, JSON может храниться в любой базе данных. То, что postgresql предоставляет с помощью JSONB, — это очень быстрая реализация с возможностью поиска.
Ответ №1:
В этой идее нет ничего плохого, за исключением того факта, что вы, похоже, сделали ее излишне сложной с использованием _get_metadata
функции. Из-за этого у вас также может возникнуть небольшая проблема с производительностью.
Такой подход с двумя таблицами является или, скорее, был довольно популярен во многих веб-приложениях, когда вы заранее не знаете, какие пары имя / значение вы будете хранить в своей таблице. Однако сейчас эта практика идет на спад благодаря решению nosql, и большинство СУБД теперь поддерживают типы данных JSON.
Django имеет встроенную поддержку превосходного поля JSONB Postgresql. Для других баз данных доступны проверенные и проверенные JSONFields, поэтому использование JSONFields даст вам довольно хорошее независимое от базы данных решение.