我需要在模型的字段中保存字典。我该怎么做?
例如我有这段代码:
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()
如果还有其他什么我应该添加,只需发表评论。谢谢!
答案 0 :(得分:20)
答案 1 :(得分:11)
在模型中存储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应用程序中还有更多好东西,这是此代码片段的来源。
答案 2 :(得分:9)
使用自定义字段类型是我首选的解决方案 - 我宁愿使用几行自定义代码,而不是支持单个字段类型的整个第三方库。 Tony Abou-Assaleh有一个很好的解决方案,但不适用于较新版本的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
答案 3 :(得分:5)
可能最干净的事情是创建另一个“产品”表并具有多对多关系。 (见这里:https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-many-relationships。在文档中,他们使用了披萨的例子,里面有很多浇头。)
另一种选择是序列化您的bill_products。在这种情况下,你会做类似的事情:
bill_products = json.dumps([rand_products])
这将在for循环之外(尽管在上面的示例中,rand_products只是一个值,因此您需要修复它。)
答案 4 :(得分:3)
您可以使用pickle模块中的序列化/反序列化:
答案 5 :(得分:3)
如果postgres是你的后端,请考虑django本机支持的hstore字段
答案 6 :(得分:2)
我认为我会将该字段创建为models.CharField(),然后将字典编码为JSON字符串并将该字符串保存到数据库中。然后,当您将其读出时,可以将JSON字符串解码回字典中。
答案 7 :(得分:0)
如果使用PostGres,则可以将其存储在本机支持的JSON字段中: https://docs.djangoproject.com/en/dev/ref/contrib/postgres/fields/#jsonfield
否则,我建议与第三方lib https://stackoverflow.com/a/16437627/803174一起使用@ramiro答案
答案 8 :(得分:0)
根据Django doc,您可以使用:
from django.contrib.postgres.fields import JSONField
from django.db import models
class Dog(models.Model):
name = models.CharField(max_length=200)
data = JSONField()
def __str__(self):
return self.name
并以此创建:
Dog.objects.create(name='Rufus', data={
'breed': 'labrador',
'owner': {
'name': 'Bob',
'other_pets': [{
'name': 'Fishy',
}],
},
})
希望这对您有所帮助。