Вопрос

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

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

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

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

Это было полезно?

Решение

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

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)

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

Другие советы

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

Я пришел к этому сообщению по четвертому результату Google для «объекта хранилища django».

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

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

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

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

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

>>> obj = SomeObject()
>>> obj.args = ['fancy', {'objects': 'inside'}]
>>> obj.save()

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

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

Установить

pip install jsonfield

Применение

from django.db import models
from jsonfield import JSONField

class MyModel(models.Model):
    json = JSONField()

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

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

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

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

Я не совсем уверен в характере проблемы, которую вы пытаетесь решить, но это звучит удивительно похоже на Расширение BigTable от 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.Возможно, стоит подумать, является ли это лучшим способом выразить ваши модели.

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

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

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

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

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

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

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

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

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

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

Вставлять случайные данные в таблицу SQL неразумно, если только это не действительно нереляционные данные.В этом случае опишите свою проблему, и мы сможем помочь.

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

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

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

Если вы используете Postgres, вы можете использовать поле hstore: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/#hstorefield.

Я использую текстовое поле и json.loads()/json.dumps()

models.py

import json
from django.db import models

class Item(models.Model):
    data = models.TextField(blank=True, null=True, default='{}')

    def save(self, *args, **kwargs):
        ## load the current string and
        ## convert string to python dictionary
        data_dict = json.loads(self.data)

        ## do something with the dictionary
        for something in somethings:
            data_dict[something] = some_function(something)

        ## if it is empty, save it back to a '{}' string,
        ## if it is not empty, convert the dictionary back to a json string
        if not data_dict:
            self.data = '{}'
        else:
            self.data = json.dumps(data_dict)


        super(Item, self).save(*args, **kwargs)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top