Domanda

Devo archiviare alcuni dati in un modello Django. Questi dati non sono uguali a tutte le istanze del modello.

Inizialmente ho pensato di sottoclassare il modello, ma sto cercando di mantenere flessibile l'applicazione. Se utilizzo le sottoclassi, dovrò creare un'intera classe ogni volta che ho bisogno di un nuovo tipo di oggetto, e non va bene. Finirò anche con molte sottoclassi solo per memorizzare un paio di campi extra.

Sento davvero che un dizionario sarebbe l'approccio migliore, ma non c'è nulla nella documentazione di Django sulla memorizzazione di un dizionario in un modello Django (o non riesco a trovarlo).

Qualche indizio?

È stato utile?

Soluzione

Se stai cercando un dizionario come dati arbitrari, probabilmente puoi usare un'impostazione a due livelli con un modello che è un contenitore e un altro modello che è coppie chiave-valore. Dovresti creare un'istanza del contenitore, creare ciascuna istanza del valore-chiave e associare il set di istanze del valore-chiave all'istanza del contenitore. Qualcosa del tipo:

class Dicty(models.Model):
    name      = models.CharField(max_length=50)

class KeyVal(models.Model):
    container = models.ForeignKey(Dicty, db_index=True)
    key       = models.CharField(max_length=240, db_index=True)
    value     = models.CharField(max_length=240, db_index=True)

Non è carino, ma ti permetterà di accedere / cercare nelle viscere del dizionario usando il DB mentre una soluzione pickle / serialize non lo farà.

Altri suggerimenti

Se non è necessario eseguire una query con nessuno di questi dati extra, è possibile memorizzarlo come dizionario serializzato. Usa repr per trasformare il dizionario in una stringa e eval per trasformare la stringa in un dizionario. Fai attenzione a eval che non ci siano dati utente nel dizionario o usa un'implementazione safe_eval.

Sono arrivato a questo post dal 4 ° risultato di Google a " django store object "

Un po 'in ritardo, ma django-picklefield mi sembra una buona soluzione.

Esempio da doc:

Per usare, basta definire un campo nel tuo modello:

>>> from picklefield.fields import PickledObjectField
>>> class SomeObject(models.Model):
>>>     args = PickledObjectField()

e assegna al campo quello che vuoi (purché sia ??selezionabile):

>>> obj = SomeObject()
>>> obj.args = ['fancy', {'objects': 'inside'}]
>>> obj.save()

Un'altra soluzione pulita e rapida è disponibile qui: https://github.com/bradjasper/django- jsonfield

Per comodità ho copiato le semplici istruzioni.

Installa

pip install jsonfield

Utilizzo

from django.db import models
from jsonfield import JSONField

class MyModel(models.Model):
    json = JSONField()

Come ha risposto Ned, non sarai in grado di interrogare " alcuni dati " se usi l'approccio con dizionario.

Se hai ancora bisogno di memorizzare dizionari, l'approccio migliore, di gran lunga, è la classe PickleField documentata nel nuovo libro di Marty Alchin Pro Django . Questo metodo utilizza le proprietà della classe Python per decapare / decomprimere un oggetto Python, solo su richiesta, memorizzato in un campo modello.

Le basi di questo approccio sono di usare contibute_to_class per aggiungere dinamicamente un nuovo campo al tuo modello e usa getattr / setattr per eseguire la serializzazione su richiesta.

Uno dei pochi esempi online che ho trovato simile è questa definizione di una JSONField .

Non sono sicuro della natura del problema che stai cercando di risolvere, ma suona curiosamente simile a BigTable Expando di Google App Engine .

Le espansioni consentono di specificare e archiviare campi aggiuntivi su un'istanza di oggetto supportata dal database in fase di esecuzione. Per citare dai documenti:

import datetime
from google.appengine.ext import db

class Song(db.Expando):
  title = db.StringProperty()

crazy = Song(title='Crazy like a diamond',
             author='Lucy Sky',
             publish_date='yesterday',
             rating=5.0)

crazy.last_minute_note=db.Text('Get a train to the station.')

Google App Engine attualmente supporta sia Python che il framework Django. Potrebbe valere la pena esaminare se questo è il modo migliore per esprimere i tuoi modelli.

I modelli di database relazionali tradizionali non hanno questo tipo di flessibilità di aggiunta di colonne. Se i tuoi tipi di dati sono abbastanza semplici, potresti rompere dalla filosofia RDBMS tradizionale e hackerare i valori in una singola colonna tramite serializzazione come @ Ned Batchelder propone; tuttavia, se devi utilizzare un RDBMS, l'ereditarietà del modello Django è probabilmente la strada da percorrere. In particolare, creerà un one-to -una chiave esterna relazione per ogni livello di derivazione.

Sono d'accordo che è necessario trattenere il riempimento di dati strutturati altrimenti in un'unica colonna. Ma se devi farlo, Django ha un XMLField costruire-in.

C'è anche JSONField negli snipplet di Django.

Essere " non uguale a tutte le istanze del modello " mi sembra una buona corrispondenza per un "database privo di schemi". CouchDB è il bambino poster di questo approccio e potresti considerarlo.

In un progetto ho spostato diversi tavoli che non hanno mai giocato molto bene con Django ORM su CouchDB e ne sono abbastanza contento. Uso couchdb-python senza nessuno dei moduli CouchDB specifici di Django. È possibile trovare una descrizione del modello di dati qui . Il movimento da cinque "modelli" in Django a 3 "modelli" in Django e un CouchDB "database" in realtà ha leggermente ridotto le righe di codice totali nella mia applicazione.

Questa domanda è vecchia, ma stavo avendo lo stesso problema, è finita qui e la risposta scelta non è più riuscita a risolvere il mio problema.

Se vuoi archiviare dizionari in Django o REST Api, o per essere usati come oggetti nel tuo front-end, o perché i tuoi dati non avranno necessariamente la stessa struttura, la soluzione che ho usato può aiutarti.

Quando si salvano i dati nell'API, utilizzare json.dump () metodo per poterlo archiviare in un formato json appropriato, come descritto in questa domanda .

Se utilizzi questa struttura, i tuoi dati saranno già nel formato json appropriato per essere richiamati nel front-end con JSON.parse () nella tua chiamata ajax (o qualsiasi altra cosa).

Ripensaci e trova le caratteristiche comuni di ogni set di dati ... quindi definisci il tuo modello. Potrebbe richiedere o meno l'uso di sottoclassi. Le chiavi esterne che rappresentano elementi comuni non devono essere evitate, ma incoraggiate quando hanno un senso.

Riporre i dati casuali in una tabella SQL non è intelligente, a meno che non siano dati non relazionali. In tal caso, definisci il tuo problema e potremmo essere in grado di aiutarti.

Django-Geo include un " DictionaryField " potresti trovare utile:

http: / /code.google.com/p/django-geo/source/browse/trunk/fields.py?r=13#49

In generale, se non è necessario eseguire una query tra i dati, utilizzare un approccio denormalizzato per evitare query aggiuntive. Le impostazioni dell'utente sono un buon esempio!

Se si utilizza Postgres, è possibile utilizzare un campo hstore: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/#hstorefield .

Uso un campo di testo e json.loads()/json.dumps()

models.py

import json
from django.db import models

class Item(models.Model):
    data = models.TextField(blank=True, null=True, default='{}')

    def save(self, *args, **kwargs):
        ## load the current string and
        ## convert string to python dictionary
        data_dict = json.loads(self.data)

        ## do something with the dictionary
        for something in somethings:
            data_dict[something] = some_function(something)

        ## if it is empty, save it back to a '{}' string,
        ## if it is not empty, convert the dictionary back to a json string
        if not data_dict:
            self.data = '{}'
        else:
            self.data = json.dumps(data_dict)


        super(Item, self).save(*args, **kwargs)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top