Dans mon modèle, je veux un champ qui a une liste de triplets. par exemple. `[[1, 3, 4], [4, 2, 6], [8, 12, 3], [3, 3, 9]]. Existe-t-il un champ pouvant stocker ces données dans la base de données?
Vous pouvez le convertir en chaîne à l'aide de JSON et le stocker en tant que chaîne.
Par exemple,
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]]'
Vous pouvez ajouter une méthode dans votre classe pour la convertir automatiquement pour vous.
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 vous utilisez Django 1.9 et postgresql, il existe une nouvelle classe appelée JSONField, vous devriez plutôt l’utiliser. Voici un lien pour cela
Il y a une bonne discussion sur les JSON et les tableaux PostgreSQL sur youtube . Regardez-le, il contient de très bonnes informations.
Si vous utilisez PostgreSQL, vous pouvez utiliser ArrayField avec un ArrayField imbriqué: https://docs.djangoproject.com/en/1.8/ref/contrib/postgres/fields/
De cette façon, la structure de données sera connue de la base de données sous-jacente. En outre, l'ORM apporte des fonctionnalités spéciales pour cela.
Notez que vous devrez cependant créer vous-même un index GIN (voir le lien ci-dessus, plus bas: https://docs.djangoproject.com/fr/1.8/ref/contrib/postgres/fields/#indexing- arrayfield ).
Si vous utilisez une version plus moderne de Django telle que 1.10 et que votre base de données est Postgres, il existe un nouveau ArrayField qu'il est préférable d'utiliser que Django-taggit ou d'autres alternatives, car il est natif du 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,
)
Je pense que cela vous aidera.
à partir de Django.db modèles d'importation importation classe ListField (models.TextField): __metaclass__ = models.SubfieldBase description = "Stocke une liste python" def __init __ (self, * args, ** kwargs): super (ListField, self) .__ init __ (* arguments, ** kwargs) def to_python (self, value): sinon valeur: valeur = [] si estinstance (valeur, liste): valeur de retour retourne ast.literal_eval (valeur) def get_prep_value (self, value): si la valeur est None: valeur de retour renvoyer unicode (valeur) def value_to_string (self, obj): valeur = self._get_val_from_obj (obj) return self.get_db_prep_value (valeur) class ListModel (models.Model): test_list = ListField ()
Exemple :
>>> 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 > [1, 2, 3], [2, 3, 4, 4]] >>>
Utilisez simplement un champ JSON fourni par ces packages tiers:
Dans ce cas, vous n'avez pas besoin de vous soucier de la sérialisation des valeurs de champ - cela se fera sous le capot.
J'espère que cela pourra aider.
Vous pouvez aplatir la liste, puis stocker les valeurs dans un fichier CommaSeparatedIntegerField . Lorsque vous relisez la base de données, regroupez simplement les valeurs en trois.
Avertissement: selon la théorie de la normalisation de la base de données, il est préférable de ne pas stocker les collections dans des champs uniques; au lieu de cela, vous serez encouragé à stocker les valeurs de ces triplets dans leurs propres champs et à les lier via des clés étrangères. Dans le monde réel, cependant, cela est parfois trop lourd/lent.
Compte tenu de ma réputation actuelle, je n'ai pas la possibilité de commenter. J'ai donc choisi de répondre aux commentaires de référence pour l'exemple de code dans répondre par Prashant Gaur (merci, Gaur - cela a été utile!) - son exemple est pour python2 depuis python3 n'a pas
unicodeméthode.
Le remplacement ci-dessous pour la fonction
get_prep_value (self, value):devrait fonctionner avec Django fonctionnant avec python3 (j'utiliserai bientôt ce code - pas encore testé) . Notez cependant que je passe
encoding = 'utf-8', errors = 'ignore'paramètres à
décoder()et
méthodes unicode (). Le codage doit correspondre à votre configuration Django settings.py et à sa transmission.
erreurs = 'ignorer'est facultatif (et peut entraîner une perte de données silencieuse au lieu d'une exception avec Django mal configuré dans de rares cas).
import sys ... def get_prep_value (self, value): si la valeur est None: valeur de retour si sys.version_info [0]> = 3: Si isinstance (out_data, tapez (b '')): return value.decode (encoding = 'utf-8', errors = 'ignore') autre: Si isinstance (out_data, tapez (b '')): renvoyer unicode (valeur, encodage = 'utf-8', errors = 'ignorer') retourne str (valeur) ...
Si vous utilisez Google App Engine ou MongoDB comme serveur principal et que vous utilisez la bibliothèque djangoappengine
, il existe un ListField
intégré qui fait exactement ce que vous voulez. En outre, il est facile d'interroger le champ de liste pour trouver tous les objets contenant un élément dans la liste.
C'est un sujet assez ancien, mais comme il est renvoyé lors de la recherche du "champ de liste Django", je vais partager le code de champ de liste Django personnalisé que j'ai modifié pour fonctionner avec Python 3 et Django 2. Il prend désormais en charge l'interface d'administration sans utiliser eval (qui est une énorme faille de sécurité dans le code de Prashant Gaur).
from Django.db import models
from typing import Iterable
class ListField(models.TextField):
"""
A custom Django field to represent lists as comma separated strings
"""
def __init__(self, *args, **kwargs):
self.token = kwargs.pop('token', ',')
super().__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
kwargs['token'] = self.token
return name, path, args, kwargs
def to_python(self, value):
class SubList(list):
def __init__(self, token, *args):
self.token = token
super().__init__(*args)
def __str__(self):
return self.token.join(self)
if isinstance(value, list):
return value
if value is None:
return SubList(self.token)
return SubList(self.token, value.split(self.token))
def from_db_value(self, value, expression, connection):
return self.to_python(value)
def get_prep_value(self, value):
if not value:
return
assert(isinstance(value, Iterable))
return self.token.join(value)
def value_to_string(self, obj):
value = self.value_from_object(obj)
return self.get_prep_value(value)