python django orm persistence

python - ¿Cómo almacenar un diccionario en un modelo de Django?



python orm (11)

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

Si aún necesita almacenar diccionarios, el mejor enfoque, con diferencia, 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 desenterrar / desengrasar un objeto python, solo bajo demanda, que se almacena en un campo de modelo.

Lo básico de este enfoque es usar el método contibute_to_class de django para agregar dinámicamente un nuevo campo a su modelo y usa getattr / setattr para hacer la serialización bajo demanda.

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

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

Al principio pensé en subclasificar el modelo, pero trato de mantener la aplicación flexible. Si utilizo subclases, tendré que 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 creo 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?



Estoy de acuerdo en que debe evitar incluir datos estructurados en una sola columna. Pero si debes hacer eso, Django tiene un build-in XMLField .

También hay JSONField en Django snipplets.


Llegué a esta publicación por el 4º resultado de google a "django store object"

Un poco tarde, pero django-picklefield parece una buena solución para mí.

Ejemplo de doc:

Para usar, solo defina un campo en su modelo:

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

y asigna lo que quieras (siempre que sea seleccionable) al campo:

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


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

Las extensiones le permiten especificar y almacenar campos adicionales en una instancia de objeto respaldada por una 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 framework Django. Puede 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 columnas. Si sus tipos de datos son lo suficientemente simples, podría romper la filosofía tradicional de RDBMS y modificar los valores en una sola columna mediante serialización, como lo propone @Ned Batchelder ; sin embargo, si tiene que usar un RDBMS, la herencia del modelo Django es probablemente el camino a seguir. En particular, creará una relación de clave externa de uno a uno para cada nivel de derivación.


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

Por conveniencia, copié las instrucciones simples.

Instalar

pip install jsonfield

Uso

from django.db import models from jsonfield import JSONField class MyModel(models.Model): json = JSONField()


Piénselo, y encuentre las características comunes de cada conjunto de datos ... luego defina su modelo. Puede requerir el uso de subclases o no. Las claves foráneas que representan aspectos comunes no deben evitarse, sino que deben promoverse cuando tengan sentido.

Rellenar datos aleatorios en una tabla SQL no es inteligente, a menos que sean datos verdaderamente no relacionales. Si ese es el caso, defina su problema y podremos ayudarlo.


Ser "no igual a todas las instancias del modelo" me parece una buena coincidencia para una "base de datos sin esquema". CouchDB es el poster de ese enfoque y podrías considerarlo.

En un proyecto moví varias tablas que nunca se jugaron muy bien con el Django ORM a CouchDB y estoy bastante contento con eso. Utilizo couchdb-python sin ninguno de los módulos CouchDB específicos de Django. Una descripción del modelo de datos se puede encontrar here . El movimiento de cinco "modelos" en Django a 3 "modelos" en Django y una "base de datos" de CouchDB realmente redujo el total de líneas de código en mi aplicación.



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


Si realmente se trata de datos arbitrarios de tipo diccionario que está buscando, probablemente pueda usar una configuración de dos niveles con un modelo que es un contenedor y otro modelo con pares clave-valor. Debería crear una instancia del contenedor, crear cada una de las instancias de valor-clave y asociar el conjunto de instancias de clave-valor con la instancia de contenedor. Algo 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 pickle / serializar no lo hará.