integerfield - django tutorial
Django: ¿Campo de lista en modelo? (8)
Con mi reputación actual no tengo la capacidad de comentar, así que elijo la respuesta haciendo referencia a los comentarios del código de muestra en la reply de (gracias, Gaur, ¡esto fue útil!) - su muestra es para python2, ya que python3 no tiene
unicode método.
El reemplazo a continuación para la función
get_prep_value(self, value): debería funcionar con Django corriendo con python3 (usaré este código pronto - pero no probado). Tenga en cuenta, sin embargo, que estoy pasando
encoding=''utf-8'', errors=''ignore'' parámetros para
decode() y
unicode() methods . La codificación debe coincidir con su configuración y configuración de Django settings.py
errors=''ignore'' es opcional (y puede dar como resultado la pérdida de datos silenciosos en lugar de la excepción con django mal configurado en casos excepcionales).
import sys ... def get_prep_value(self, value): if value is None: return value if sys.version_info[0] >= 3: if isinstance(out_data, type(b'''')): return value.decode(encoding=''utf-8'', errors=''ignore'') else: if isinstance(out_data, type(b'''')): return unicode(value, encoding=''utf-8'', errors=''ignore'') return str(value) ...
En mi modelo, quiero un campo que tenga una lista de trillizos. ej. `[[1, 3, 4], [4, 2, 6], [8, 12, 3], [3, 3, 9]]. ¿Hay algún campo que pueda almacenar estos datos en la base de datos?
Creo que te ayudará.
from django.db import models import ast class ListField(models.TextField): __metaclass__ = models.SubfieldBase description = "Stores a python list" def __init__(self, *args, **kwargs): super(ListField, self).__init__(*args, **kwargs) def to_python(self, value): if not value: value = [] if isinstance(value, list): return value return ast.literal_eval(value) def get_prep_value(self, value): if value is None: return value return unicode(value) def value_to_string(self, obj): value = self._get_val_from_obj(obj) return self.get_db_prep_value(value) class ListModel(models.Model): test_list = ListField()
Ejemplo:
>>> ListModel.objects.create(test_list= [[1,2,3], [2,3,4,4]]) >>> ListModel.objects.get(id=1) >>> o = ListModel.objects.get(id=1) >>> o.id 1L >>> o.test_list [[1, 2, 3], [2, 3, 4, 4]] >>>
Puede aplanar la lista y luego almacenar los valores en un CommaSeparatedIntegerField . Cuando vuelves a leer desde la base de datos, simplemente vuelve a agrupar los valores en tres.
Descargo de responsabilidad: de acuerdo con la teoría de normalización de la base de datos, es mejor no almacenar colecciones en campos individuales; en su lugar, se recomienda almacenar los valores en esos trillizos en sus propios campos y vincularlos a través de claves externas. En el mundo real, sin embargo, a veces eso es demasiado engorroso / lento.
Puede convertirlo en cadena usando JSON y almacenarlo como cadena.
Por ejemplo,
In [3]: json.dumps([[1, 3, 4], [4, 2, 6], [8, 12, 3], [3, 3, 9]])
Out[3]: ''[[1, 3, 4], [4, 2, 6], [8, 12, 3], [3, 3, 9]]''
Puede agregar un método en su clase para convertirlo automáticamente.
import json
class Foobar(models.Model):
foo = models.CharField(max_length=200)
def set_foo(self, x):
self.foo = json.dumps(x)
def get_foo(self):
return json.loads(self.foo)
Si está utilizando Django 1.9 y postgresql, hay una nueva clase llamada JSONField, debería usarla en su lugar. Aquí hay un enlace para eso
Hay una buena charla sobre JSONs y Arrays de PostgreSQL en youtube . Míralo, tiene muy buena información.
Si está utilizando Google App Engine o MongoDB como su back-end, y está utilizando la biblioteca djangoappengine
, hay un ListField
que hace exactamente lo que desea. Además, es fácil consultar el Listfield para encontrar todos los objetos que contienen un elemento en la lista.
Si está utilizando PostgreSQL, puede usar ArrayField con un ArrayField anidado: https://docs.djangoproject.com/en/1.8/ref/contrib/postgres/fields/
De esta manera, la estructura de datos será conocida por la base de datos subyacente. Además, el ORM le brinda una funcionalidad especial.
Sin embargo, tenga en cuenta que deberá crear un índice GIN usted mismo (consulte el enlace anterior, más abajo: https://docs.djangoproject.com/en/1.8/ref/contrib/postgres/fields/#indexing-arrayfield ) .
Si está utilizando una versión más moderna de Django como 1.10 y su base de datos es Postgres, hay un nuevo ArrayField que es mejor usar que django-taggit u otras alternativas, ya que es nativo del framework Django.
from django.db import models
from django.contrib.postgres.fields import ArrayField
class ChessBoard(models.Model):
board = ArrayField(
ArrayField(
models.CharField(max_length=10, blank=True),
size=8,
),
size=8,
)
Solo use un campo JSON que proporcionan estos paquetes de terceros:
En este caso, no es necesario que se preocupe por la serialización de los valores de campo: se realizará bajo el capó.
Espero que ayude.