2012-03-13 3 views
18

Ho bisogno di salvare un dizionario nel campo di un modello. Come lo faccio?Come memorizzare un dizionario nel campo di un modello di database Django

Per esempio io ho questo codice:

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() 

Cosa scrivo per "bill_products =" in modo da risparmiare alcuni prodotti a caso, dal mio modello prodotto a questo disegno di legge?

Questa è la descrizione del disegno di legge modello:

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

E anche descrizione del modello del prodotto:

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

Se c'è qualcos'altro che dovrei aggiungere solo lasciare un commento. Grazie!

+0

Che diavolo è un "modello di database pitone"? Stai usando un particolare ORM o framework? questo sembra un po 'django-ish' – SingleNegationElimination

+1

Sì, è Django. Sto solo iniziando a lavorarci per poter mischiare "Python" con "Django". Cambierò il titolo. –

risposta

6

Probabilmente la cosa più pulita da fare sarebbe creare un'altra tabella "Prodotti" e avere una relazione molti-a-molti. (Vedi qui: https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-many-relationships. Nei documenti usano l'esempio di una pizza con molti condimenti).

L'altra opzione sarebbe quella di serializzare i tuoi bill_products. In quel caso, devi fare qualcosa di simile:

bill_products = json.dumps([rand_products]) 

Questo sarebbe al di fuori del ciclo for (anche se, nel tuo esempio sopra, rand_products è un solo valore, quindi avrai bisogno di risolvere questo) .

+0

Se potessi fornire un esempio sarebbe molto bello. Temo di non aver capito esattamente come tradurre una relazione molti-a-molti con il mio codice. Sono sulla giusta strada dell'idea con il salvataggio di un array con i nomi dei prodotti in quel campo? O potrei farlo in un approccio più semplice? –

+0

@reos Sei sulla buona strada. Ecco un esempio completo: https://www.djangoproject.com/documentation/0_91/models/many_to_many/ – gdw2

1

Penso che vorrei creare il campo come models.CharField() e quindi codificare il dizionario come stringa JSON e salvare quella stringa nel database. Quindi puoi decodificare la stringa JSON in un dizionario quando lo leggi.

+0

Ho aggiunto la descrizione del modello di Bill. –

7

Un modo conveniente per memorizzare una rappresentazione JSON in un modello è quello di utilizzare un tipo di campo personalizzato:

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) 

ho salvato questo utils/fields.py e nel mio modello from utils.fields import JSONField. Ci sono molti altri gadget nell'app django-annoying, da cui proviene questo frammento.

16

Ho appena scoperto il pacchetto django-jsonfield, che

è un campo riutilizzabile Django che consente di memorizzare convalidato JSON nel modello.

Sembra un'opzione valida per ottenere ciò che si desidera.

+2

Grazie per l'aggiornamento. È bene sapere, anche se questo problema è stato risolto molto tempo fa. –

3

Se postgres è il vostro backend, considera il campo hstore, che ha il supporto nativo da Django

+0

Grazie per la risposta, ma questo è stato a lungo risolto e risolto. E il back-end per questo era SQLLite –

6

utilizzando un tipo di campo personalizzato è il mio soluzione preferita - preferirei avere poche righe di codice personalizzato che supportare un'intera libreria di terze parti per un singolo tipo di campo. Tony Abou-Assaleh ha un'ottima soluzione, ma non funzionerà con le versioni più recenti di Django.

Questa è verificato per lavorare 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