Django: доступ к таблице через dict-подобный интерфейс

#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 даст вам довольно хорошее независимое от базы данных решение.