2012-03-13 22 views
18

Necesito guardar un diccionario en el campo de un modelo. ¿Cómo puedo hacer eso?Cómo almacenar un diccionario en el campo de un modelo de base de datos Django

Por ejemplo, tengo este código:

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é debo escribir para "bill_products =" por lo que ahorra algunos productos al azar, desde mi modelo del producto a este proyecto de ley?

Esta es la descripción del proyecto de ley modelo:

class Bill(models.Model): 
    name = models.CharField(max_length=255) 
    date = models.DateTimeField(auto_now_add=True) 
    products = models.ManyToManyField(Product, related_name="bills") 

Y también la descripción del modelo del producto:

class Product(models.Model): 
    name = models.CharField(max_length=255) 
    price = models.IntegerField() 

Si hay algo más que debería añadir simplemente dejar un comentario. ¡Gracias!

+0

¿Qué diablos es un "modelo de base de datos de Python"? ¿Estás usando un ORM o marco particular? esto se ve un poco 'django-ish' – SingleNegationElimination

+1

Sí, es Django. Estoy empezando a trabajar con él, así que podría mezclar "Python" con "Django". Cambiaré el título. –

Respuesta

6

Probablemente lo más limpio sería crear otra tabla de "Productos" y tener una relación de muchos a muchos. (Consulte aquí: https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-many-relationships. En los documentos, usan el ejemplo de una pizza que tiene muchos ingredientes).

La otra opción sería serializar sus bill_products. En ese caso, usted haría algo como:

bill_products = json.dumps([rand_products]) 

Esto estaría fuera del bucle (aunque, en su ejemplo anterior, rand_products es un solo valor, por lo que tendrá que arreglar eso) .

+0

Si pudiera dar un ejemplo, sería muy bueno. Me temo que no entendí exactamente cómo traducir una relación de muchos a muchos a mi código. ¿Estoy en la ruta de la idea correcta al guardar una matriz con nombres de productos en ese campo? ¿O podría hacerlo de una manera más simple? –

+0

@reos Estás en el camino correcto. Aquí hay un ejemplo completo: https://www.djangoproject.com/documentation/0_91/models/many_to_many/ – gdw2

1

Creo que crearía el campo como models.CharField() y luego codificaría el diccionario como una cadena JSON y guardaría esa cadena en la base de datos. Luego puede decodificar la cadena JSON nuevamente en un diccionario cuando la lea.

+0

Agregué la descripción del modelo de Bill. –

7

Una forma conveniente de almacenar una representación JSON en un modelo es utilizar un tipo de campo personalizado:

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) 

ahorré este utils/fields.py y en mi modelo from utils.fields import JSONField. Hay muchos más extras en la aplicación django-annoying, que es de donde proviene este fragmento.

16

acabo de descubrir el paquete django-jsonfield, que

es un campo de Django reutilizable que le permite almacenar JSON validado en su modelo.

Parece una opción viable para lograr lo que desea.

+2

Gracias por la actualización. Es bueno saberlo, incluso si este problema se solucionó hace mucho tiempo. –

3

Si postgres es su backend, tenemos en cuenta el campo hstore que tiene soporte nativo de Django

+0

Gracias por su respuesta, pero esto se ha respondido y resuelto durante mucho tiempo. Y el backend para esto era SQLLite –

6

utilizando un tipo de campo personalizado es mi solución preferida: prefiero tener algunas líneas de código personalizado que admitir una biblioteca de terceros completa para un solo tipo de campo. Tony Abou-Assaleh tiene una gran solución, pero no funcionará para las versiones más nuevas de Django.

Esto se verifica a trabajar con 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 
Cuestiones relacionadas