Как сохранить словарь на модели Django? - PullRequest
50 голосов
/ 31 декабря 2008

Мне нужно хранить некоторые данные в модели Django. Эти данные не равны всем экземплярам модели.

Сначала я подумал о создании подкласса модели, но я пытаюсь сохранить гибкость приложения. Если я использую подклассы, мне нужно будет создавать целый класс каждый раз, когда мне нужен новый тип объекта, и это бесполезно. Я также получу множество подклассов только для хранения пары дополнительных полей.

Я действительно чувствую, что словарь будет лучшим подходом, но в документации Django нет ничего о том, как сохранить словарь в модели Django (или я не могу его найти).

Есть какие-нибудь подсказки?

Ответы [ 13 ]

37 голосов
/ 31 декабря 2008

Если это действительно словарь, подобный произвольным данным, которые вы ищете, вы, вероятно, можете использовать двухуровневую настройку с одной моделью, которая является контейнером, и другой моделью, которая представляет собой пары ключ-значение. Вы должны создать экземпляр контейнера, создать каждый из экземпляров значения ключа и связать набор экземпляров значения ключа с экземпляром контейнера. Что-то вроде:

class Dicty(models.Model):
    name      = models.CharField(max_length=50)

class KeyVal(models.Model):
    container = models.ForeignKey(Dicty, db_index=True)
    key       = models.CharField(max_length=240, db_index=True)
    value     = models.CharField(max_length=240, db_index=True)

Это не красиво, но оно позволит вам получить доступ / искать во внутреннем словаре словаря с помощью БД, тогда как решение для засолки / сериализации не будет.

14 голосов
/ 31 декабря 2008

Если вам не нужно запрашивать какие-либо из этих дополнительных данных, вы можете сохранить их как сериализованный словарь. Используйте repr, чтобы превратить словарь в строку, и eval, чтобы превратить строку в словарь. Будьте внимательны с eval, чтобы в словаре не было пользовательских данных, или используйте реализацию safe_eval.

11 голосов
/ 31 июля 2013

Еще одно чистое и быстрое решение можно найти здесь: https://github.com/bradjasper/django-jsonfield

Для удобства я скопировал простые инструкции.

Установить

pip install jsonfield

Usage

from django.db import models
from jsonfield import JSONField

class MyModel(models.Model):
    json = JSONField()
11 голосов
/ 19 сентября 2011

Я пришел к этому сообщению по 4-му результату Google в "django store object"

Немного поздно, но Джанго-Пиклфилд выглядит для меня хорошим решением.

Пример из документа:

Чтобы использовать, просто определите поле в вашей модели:

>>> from picklefield.fields import PickledObjectField
>>> class SomeObject(models.Model):
>>>     args = PickledObjectField()

и назначьте на поле все, что вам нравится (если это возможно):

>>> obj = SomeObject()
>>> obj.args = ['fancy', {'objects': 'inside'}]
>>> obj.save()
7 голосов
/ 31 декабря 2008

Как ответил Нед, вы не сможете запросить «некоторые данные», если будете использовать словарный подход.

Если вам все еще нужно хранить словари, то лучшим подходом, безусловно, является класс PickleField, описанный в новой книге Марти Алчина Pro Django . Этот метод использует свойства класса Python для выбора / отмены выбора объекта Python, только по запросу, который хранится в поле модели.

Основой этого подхода является использование метода contibute_to_class django для динамического добавления нового поля в вашу модель и использование getattr / setattr для сериализации по требованию.

Один из немногих онлайн-примеров, которые я смог найти, похож на это определение JSONField .

5 голосов
/ 31 декабря 2008

Я не совсем уверен в природе проблемы, которую вы пытаетесь решить, но она странно похожа на BigTable Expando из Google App Engine .

Расширения позволяют указывать и хранить дополнительные поля в экземпляре объекта, поддерживаемого базой данных, во время выполнения. Цитировать из документов:

import datetime
from google.appengine.ext import db

class Song(db.Expando):
  title = db.StringProperty()

crazy = Song(title='Crazy like a diamond',
             author='Lucy Sky',
             publish_date='yesterday',
             rating=5.0)

crazy.last_minute_note=db.Text('Get a train to the station.')

Google App Engine в настоящее время поддерживает как Python, так и инфраструктуру Django. Может быть стоит посмотреть, если это лучший способ выразить свои модели.

Традиционные модели реляционных баз данных не имеют такой гибкости добавления столбцов. Если ваши типы данных достаточно просты, вы можете отказаться от традиционной философии СУБД и взломать значения в один столбец с помощью сериализации, как предлагает @ Ned Batchelder ; однако, если у вас есть для использования СУБД, вероятно, вам следует воспользоваться наследованием модели Django. В частности, он создаст отношение внешнего ключа один к одному для каждого уровня деривации.

3 голосов
/ 02 августа 2018

Этот вопрос старый, но у меня возникла та же проблема, она закончилась, и выбранный ответ больше не мог решить мою проблему.

Если вы хотите хранить словари в Django или REST Api, которые будут использоваться как объекты в вашем интерфейсе, или потому что ваши данные не обязательно будут иметь ту же структуру, то решение, которое я использовал, может вам помочь.

При сохранении данных в вашем API используйте метод json.dump () , чтобы иметь возможность сохранить их в правильном формате json, как описано в этом вопросе .

Если вы используете эту структуру, ваши данные уже будут в соответствующем формате json, который будет вызываться во внешнем интерфейсе с помощью JSON.parse () в вашем вызове ajax (или как угодно).

3 голосов
/ 13 мая 2009

Я согласен с тем, что вам нужно воздерживаться от добавления данных, структурированных по-другому, в один столбец. Но если вы должны это сделать, Django имеет встроенную XMLField .

Есть также JSONField во фрагментах Django.

3 голосов
/ 04 января 2009

Быть «не равным всем экземплярам модели» звучит для меня как хорошее совпадение с «базой данных без схемы». CouchDB является потомком для этого подхода, и вы можете подумать об этом.

В проекте я переместил несколько таблиц, которые никогда не играли очень хорошо с Django ORM, в CouchDB, и я очень доволен этим. Я использую couchdb-python без каких-либо специфичных для Django модулей CouchDB. Описание модели данных можно найти здесь . Переход от пяти «моделей» в Django к 3 «моделям» в Django и одной «базе данных» CouchDB фактически немного уменьшил общее количество строк кода в моем приложении.

2 голосов
/ 13 мая 2009

Django-Geo включает «DictionaryField», которое может оказаться полезным:

http://code.google.com/p/django-geo/source/browse/trunk/fields.py?r=13#49

В общем, если вам не нужно выполнять запросы по данным, используйте денормализованный подход, чтобы избежать дополнительных запросов. Пользовательские настройки - довольно хороший пример!

...