Как сохранить словарь в поле модели базы данных Django
Мне нужно сохранить словарь в поле модели. Как это сделать?
Например, у меня есть этот код:
def create_random_bill(self):
name_chars = re.compile("[a-zA-Z0-9 -_]")
bill_name = "".join(random.choice(name_chars for x in range(10)))
rand_products = random.randint(1,100)
for x in rand_products:
bill_products =
new_bill = Bill.new(name=bill_name, date=datetime.date, products=bill_products)
new_bill.save()
Что я пишу для "bill_products =", чтобы сохранить некоторые случайные продукты из моей модели продукта в этот счет?
Это описание модели счета:
class Bill(models.Model):
name = models.CharField(max_length=255)
date = models.DateTimeField(auto_now_add=True)
products = models.ManyToManyField(Product, related_name="bills")
А также описание модели продукта:
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.IntegerField()
Если есть что-то еще, я должен добавить только оставить комментарий. Спасибо!
Ответы
Ответ 1
Вероятно, самой чистой задачей было бы создать другую таблицу "Продукты" и иметь отношения "многие ко многим". (См. Здесь: https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-many-relationships. В документах они используют пример пиццы с большим количеством начинок.)
Другой вариант - это сериализовать ваши bill_products. В этом случае вы бы сделали что-то вроде:
bill_products = json.dumps([rand_products])
Это будет за пределами цикла for (хотя в приведенном выше примере rand_products - это только одно значение, поэтому вам нужно это исправить).
Ответ 2
Я только что обнаружил пакет django-jsonfield, который
- это многократно используемое поле Django, которое позволяет хранить проверенную JSON в вашей модели.
Похож на реальный вариант для достижения желаемого.
Ответ 3
Одним удобным способом хранения JSON-представления в модели является использование настраиваемого типа поля:
class JSONField(models.TextField):
"""
JSONField is a generic textfield that neatly serializes/unserializes
JSON objects seamlessly.
Django snippet #1478
example:
class Page(models.Model):
data = JSONField(blank=True, null=True)
page = Page.objects.get(pk=5)
page.data = {'title': 'test', 'type': 3}
page.save()
"""
__metaclass__ = models.SubfieldBase
def to_python(self, value):
if value == "":
return None
try:
if isinstance(value, basestring):
return json.loads(value)
except ValueError:
pass
return value
def get_db_prep_save(self, value, *args, **kwargs):
if value == "":
return None
if isinstance(value, dict):
value = json.dumps(value, cls=DjangoJSONEncoder)
return super(JSONField, self).get_db_prep_save(value, *args, **kwargs)
Я сохранил этот utils/fields.py и в моей модели from utils.fields import JSONField
. В django-annoying добавлено еще много полезных свойств: здесь был создан этот фрагмент.
Ответ 4
Использование настраиваемого типа поля - это мое предпочтительное решение. Я бы предпочел иметь несколько строк пользовательского кода, чем поддерживать всю стороннюю библиотеку для одного типа поля. У Тони Абу-Ассале есть отличное решение, но он не будет работать для более новых версий Django.
Это проверено для работы с Django 1.10.4
import json
from django.db import models
from django.core.serializers.json import DjangoJSONEncoder
class JSONField(models.TextField):
"""
JSONField is a generic textfield that neatly serializes/unserializes
JSON objects seamlessly.
Django snippet #1478
example:
class Page(models.Model):
data = JSONField(blank=True, null=True)
page = Page.objects.get(pk=5)
page.data = {'title': 'test', 'type': 3}
page.save()
"""
def to_python(self, value):
if value == "":
return None
try:
if isinstance(value, str):
return json.loads(value)
except ValueError:
pass
return value
def from_db_value(self, value, *args):
return self.to_python(value)
def get_db_prep_save(self, value, *args, **kwargs):
if value == "":
return None
if isinstance(value, dict):
value = json.dumps(value, cls=DjangoJSONEncoder)
return value
Ответ 5
Вы можете использовать сериализацию/десериализацию из модуля рассола:
http://docs.python.org/library/pickle.html
Ответ 6
Если postgres - это ваш бэкэнд, рассмотрите поле hstore, которое имеет встроенную поддержку от django
Ответ 7
Я думаю, что я создам поле как models.CharField(), а затем закодирует словарь как строку JSON и сохранит эту строку в базе данных. Затем вы можете декодировать строку JSON обратно в словарь, когда вы его прочитали.