J'ai besoin d'enregistrer un dictionnaire dans le champ d'un modèle. Comment je fais ça?
Par exemple, j'ai ce code:
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()
Qu'est-ce que j'écris pour "bill_products =" afin qu'il enregistre des produits aléatoires, de mon modèle de produit à cette facture?
Voici la description du modèle du projet de loi:
class Bill(models.Model):
name = models.CharField(max_length=255)
date = models.DateTimeField(auto_now_add=True)
products = models.ManyToManyField(Product, related_name="bills")
Et aussi la description du modèle du produit:
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.IntegerField()
S'il y a autre chose que je devrais ajouter, laissez simplement un commentaire. Merci!
La chose la plus propre à faire serait probablement de créer une autre table "Produits" et d'avoir une relation plusieurs-à-plusieurs. (Voir ici: https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-many-relationships . Dans les documents, ils utilisent l'exemple d'une pizza ayant de nombreuses garnitures.)
L'autre option serait de sérialiser vos produits bill_product. Dans ce cas, vous feriez quelque chose comme:
bill_products = json.dumps([Rand_products])
Ce serait en dehors de la boucle for (bien que, dans votre exemple ci-dessus, Rand_products ne soit qu'une seule valeur, vous devrez donc corriger cela).
Je viens de découvrir le paquet Django-jsonfield , qui
est un champ Django réutilisable qui vous permet de stocker du JSON validé dans votre modèle.
Ressemble à une option viable pour réaliser ce que vous voulez.
Une façon pratique de stocker une représentation JSON dans un modèle consiste à utiliser un type de champ personnalisé:
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)
J'ai enregistré ce utils/fields.py et dans mon modèle from utils.fields import JSONField
. Il y a beaucoup plus de goodies dans l'application Django-ennuyeux , d'où vient cet extrait.
L'utilisation d'un type de champ personnalisé est ma solution préférée - je préfère avoir quelques lignes de code personnalisé que de prendre en charge une bibliothèque tierce entière pour un seul type de champ. Tony Abou-Assaleh a une excellente solution, mais ne fonctionnera pas pour les nouvelles versions de Django.
Il est vérifié que cela fonctionne avec 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
Vous pouvez utiliser la sérialisation/désérialisation à partir du module de décapage:
Si postgres est votre backend, considérez le champ hstore qui a un support natif de Django
Je pense que je créerais le champ en tant que models.CharField () puis encoderais le dictionnaire en tant que chaîne JSON et enregistrerais cette chaîne dans la base de données. Ensuite, vous pouvez décoder la chaîne JSON dans un dictionnaire lorsque vous la lisez.
Si vous utilisez PostGres, vous pouvez le stocker dans le champ JSON pris en charge nativement: https://docs.djangoproject.com/en/dev/ref/contrib/postgres/fields/#jsonfield
Sinon, je recommanderais la réponse @ramiro avec une bibliothèque tierce https://stackoverflow.com/a/16437627/803174