Pregunta

Necesito almacenar algunos datos en un modelo Django. Estos datos no son iguales a todas las instancias del modelo.

Al principio pensé en subclasificar el modelo, pero estoy tratando de mantener la aplicación flexible. Si uso subclases, necesitaré crear una clase completa cada vez que necesite un nuevo tipo de objeto, y eso no es bueno. También terminaré con muchas subclases solo para almacenar un par de campos adicionales.

Realmente siento que un diccionario sería el mejor enfoque, pero no hay nada en la documentación de Django sobre el almacenamiento de un diccionario en un modelo de Django (o no puedo encontrarlo).

¿Alguna pista?

¿Fue útil?

Solución

Si en realidad está buscando un diccionario como datos arbitrarios, probablemente pueda usar una configuración de dos niveles con un modelo que sea un contenedor y otro modelo que sea pares clave-valor. Crearía una instancia del contenedor, crearía cada una de las instancias de valor clave y asociaría el conjunto de instancias de valor clave con la instancia de contenedor. Algo así como:

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)

No es bonito, pero le permitirá acceder / buscar en las entrañas del diccionario utilizando la base de datos, mientras que una solución de pickle / serialización no lo hará.

Otros consejos

Si no necesita consultar con ninguno de estos datos adicionales, entonces puede almacenarlo como un diccionario serializado. Utilice repr para convertir el diccionario en una cadena y eval para volver a convertir la cadena en un diccionario. Tenga cuidado con la evaluación de que no hay datos de usuario en el diccionario, o use una implementación segura_eval.

Llegué a esta publicación por el cuarto resultado de Google para " objeto de tienda django "

Un poco tarde, pero django-picklefield me parece una buena solución.

Ejemplo de doc:

Para usar, solo define un campo en tu modelo:

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

y asigne lo que quiera (siempre que sea seleccionable) al campo:

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

Otra solución limpia y rápida se puede encontrar aquí: https://github.com/bradjasper/django- jsonfield

Por conveniencia, copié las sencillas instrucciones.

Instalar

pip install jsonfield

Usuario

from django.db import models
from jsonfield import JSONField

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

Como respondió Ned, no podrá consultar " algunos datos " si usa el enfoque de diccionario.

Si aún necesita almacenar diccionarios, el mejor método es la clase PickleField documentada en el nuevo libro de Marty Alchin Pro Django . Este método utiliza las propiedades de la clase Python para encurtir / desarmar un objeto de Python, solo a pedido, que se almacena en un campo modelo.

Lo básico de este enfoque es utilizar contibute_to_class para agregar dinámicamente un nuevo campo a su modelo y usa getattr / setattr para realizar la serialización a pedido.

Uno de los pocos ejemplos en línea que podría encontrar que es similar es esta definición de JSONField .

No estoy muy seguro de la naturaleza del problema que estás tratando de resolver, pero suena curiosamente similar a BigTable Expando de Google App Engine .

Los Expandos le permiten especificar y almacenar campos adicionales en una instancia de objeto respaldada por base de datos en tiempo de ejecución. Para citar de los documentos:

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 actualmente es compatible con Python y el marco Django. Podría valer la pena investigar si esta es la mejor manera de expresar sus modelos.

Los modelos tradicionales de bases de datos relacionales no tienen este tipo de flexibilidad de adición de columna. Si sus tipos de datos son lo suficientemente simples, puede romper con la filosofía tradicional RDBMS y piratear valores en una sola columna mediante la serialización como @ Ned Batchelder propone; sin embargo, si tiene para usar un RDBMS, la herencia del modelo Django es probablemente el camino a seguir. En particular, creará un one-to -una relación de clave externa para cada nivel de derivación.

Estoy de acuerdo en que debe abstenerse de rellenar datos estructurados de otra manera en una sola columna. Pero si debe hacerlo, Django tiene un XMLField incorporado.

También hay JSONField en los snipplets de Django.

Ser " no es igual a todas las instancias del modelo " me parece una buena combinación para una "base de datos libre de esquemas". CouchDB es el elemento secundario para ese enfoque y usted podría considerar eso.

En un proyecto, moví varias mesas que nunca jugaron muy bien con Django ORM a CouchDB y estoy bastante contento con eso. Yo uso couchdb-python sin ninguno de los módulos CouchDB específicos de Django. Se puede encontrar una descripción del modelo de datos aquí . El movimiento de cinco '' modelos '' en Django a 3 '' modelos '' en Django y una base de datos CouchDB " en realidad redujo ligeramente las líneas totales de código en mi aplicación.

Esta pregunta es antigua, pero tenía el mismo problema, terminé aquí y la respuesta elegida ya no pudo resolver mi problema.

Si desea almacenar diccionarios en Django o REST Api, ya sea para usarlos como objetos en su parte frontal, o porque sus datos no necesariamente tendrán la misma estructura, la solución que utilicé puede ayudarlo.

Al guardar los datos en su API, use json.dump () método para poder almacenarlo en un formato json adecuado, como se describe en esta pregunta .

Si usa esta estructura, sus datos ya estarán en el formato json apropiado para ser llamado en el front end con JSON.parse () en tu llamada ajax (o lo que sea).

Piénsalo, y encuentra las características comunes de cada conjunto de datos ... luego define tu modelo. Puede requerir el uso de subclases o no. Las claves foráneas que representan puntos en común no se deben evitar, pero se deben alentar cuando tienen sentido.

El relleno de datos aleatorios en una tabla SQL no es inteligente, a menos que sean datos verdaderamente no relacionales. Si ese es el caso, define tu problema y podremos ayudarte.

Django-Geo incluye un " DictionaryField " puede ser útil:

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

En general, si no necesita consultar a través de los datos, utilice un enfoque desnormalizado para evitar consultas adicionales. ¡La configuración del usuario es un buen ejemplo!

Si está usando Postgres, puede usar un campo hstore: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/#hstorefield .

Uso un campo de texto y 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)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top