web-dev-qa-db-fra.com

Comment sérialiser une instance de modèle dans Django?

Il y a beaucoup de documentation sur la façon de sérialiser un modèle QuerySet, mais comment sérialiser en JSON les champs d'une instance de modèle?

136
Jason Christa

Vous pouvez facilement utiliser une liste pour encapsuler l'objet requis. C'est tout ce dont Django les sérialiseurs ont besoin pour le sérialiser correctement, par exemple:

from Django.core import serializers

# assuming obj is a model instance
serialized_obj = serializers.serialize('json', [ obj, ])
217
xaralis

Si vous traitez avec une liste d'instances de modèles, le mieux que vous puissiez faire est d'utiliser serializers.serialize(), cela répondra parfaitement à vos besoins.

Cependant, vous devez faire face à un problème en essayant de sérialiser un objet nique, pas un list d'objets. De cette façon, pour vous débarrasser de différents hacks, utilisez simplement le model_to_dict De Django (si je ne me trompe pas, serializers.serialize() s'appuie également dessus):

from Django.forms.models import model_to_dict

# assuming obj is your model instance
dict_obj = model_to_dict( obj )

Vous avez maintenant besoin d’un appel direct json.dumps Pour le sérialiser en json:

import json
serialized = json.dumps(dict_obj)

C'est ça! :)

55
Pavel Daynyak

Pour éviter le wrapper de tableau, supprimez-le avant de renvoyer la réponse:

import json
from Django.core import serializers

def getObject(request, id):
    obj = MyModel.objects.get(pk=id)
    data = serializers.serialize('json', [obj,])
    struct = json.loads(data)
    data = json.dumps(struct[0])
    return HttpResponse(data, mimetype='application/json')

J'ai trouvé cet article intéressant sur le sujet aussi:

http://timsaylor.com/convert-Django-model-instances-todictionaries

Il utilise Django.forms.models.model_to_dict, qui semble être l'outil idéal pour ce travail.

41
Julian

Il semble que ce que vous demandez concerne la sérialisation de la structure de données d’une instance de modèle Django aux fins d’interopérabilité. Les autres affiches sont correctes: si vous souhaitiez utiliser le formulaire sérialisé avec une application python pouvant interroger la base de données via l’API de Django, vous voudriez alors sérialiser un queryset avec un seul objet. Si, par contre, vous avez besoin d’un moyen de regonfler l’instance de modèle ailleurs sans toucher à la base de données ni utiliser Django, vous avez un peu de travail à faire.

Voici ce que je fais:

D'abord, j'utilise demjson pour la conversion. C'est ce que j'ai trouvé en premier, mais ce n'est peut-être pas le meilleur. Mon implémentation dépend de l'une de ses fonctionnalités, mais il devrait exister des méthodes similaires avec d'autres convertisseurs.

Deuxièmement, implémentez une méthode json_equivalent Sur tous les modèles que vous pourriez avoir besoin de sérialiser. C’est une méthode magique pour demjson, mais c’est probablement une chose à laquelle vous allez vouloir penser quelle que soit l’implémentation que vous choisissez. L'idée est que vous retourniez un objet directement convertible en json (c'est-à-dire un tableau ou un dictionnaire). Si vous voulez vraiment le faire automatiquement:

def json_equivalent(self):
    dictionary = {}
    for field in self._meta.get_all_field_names()
        dictionary[field] = self.__getattribute__(field)
    return dictionary

Cela ne vous sera utile que si vous avez une structure de données complètement plate (pas de ForeignKeys, uniquement des nombres et des chaînes dans la base de données, etc.). Sinon, vous devriez sérieusement réfléchir à la bonne façon de mettre en œuvre cette méthode.

Troisièmement, appelez demjson.JSON.encode(instance) et vous avez ce que vous voulez.

10
David Berger

Si vous demandez comment sérialiser un seul objet à partir d'un modèle et que vous savez vous n'obtiendrez qu'un seul objet dans le jeu de requête (par exemple, en utilisant objects.get), utilisez quelque chose comme: :

import Django.core.serializers
import Django.http
import models

def jsonExample(request,poll_id):
    s = Django.core.serializers.serialize('json',[models.Poll.objects.get(id=poll_id)])
    # s is a string with [] around it, so strip them off
    o=s.strip("[]")
    return Django.http.HttpResponse(o, mimetype="application/json")

qui vous donnerait quelque chose de la forme:

{"pk": 1, "model": "polls.poll", "fields": {"pub_date": "2013-06-27T02:29:38.284Z", "question": "What's up?"}}
8
benlast

Il y a une bonne réponse à cela et je suis surpris que cela n'ait pas été mentionné. Avec quelques lignes, vous pouvez gérer les dates, les modèles et tout le reste.

Créez un encodeur personnalisé pouvant gérer les modèles:

from Django.forms import model_to_dict
from Django.core.serializers.json import DjangoJSONEncoder
from Django.db.models import Model

class ExtendedEncoder(DjangoJSONEncoder):

    def default(self, o):

        if isinstance(o, Model):
            return model_to_dict(o)

        return super().default(o)

Maintenant, utilisez-le lorsque vous utilisez json.dumps

json.dumps(data, cls=ExtendedEncoder)

Maintenant, les modèles, les dates et tout peuvent être sérialisés et il n'est pas nécessaire que ce soit dans un tableau ou sérialisés et non sérialisés.

7
kagronick

J'ai résolu ce problème en ajoutant une méthode de sérialisation à mon modèle:

def toJSON(self):
    import simplejson
    return simplejson.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))

Voici l'équivalent verbal pour ceux qui sont opposés aux one-liners:

def toJSON(self):
    fields = []
    for field in self._meta.fields:
        fields.append(field.name)

    d = {}
    for attr in fields:
        d[attr] = getattr(self, attr)

    import simplejson
    return simplejson.dumps(d)

_meta.fields est une liste ordonnée de champs de modèle auxquels on peut accéder à partir d'instances et du modèle lui-même.

5
davidchambers

Voici ma solution pour cela, qui vous permet de personnaliser facilement le JSON et d'organiser les enregistrements associés.

Tout d'abord implémenter une méthode sur le modèle. J'appelle est json mais vous pouvez l'appeler comme bon vous semble, par exemple:

class Car(Model):
    ...
    def json(self):
        return {
            'manufacturer': self.manufacturer.name,
            'model': self.model,
            'colors': [color.json for color in self.colors.all()],
        }

Alors dans la vue je fais:

data = [car.json for car in Car.objects.all()]
return HttpResponse(json.dumps(data), content_type='application/json; charset=UTF-8', status=status)
5
DanH

Utilisez la liste, cela résoudra le problème

Étape 1:

 result=YOUR_MODELE_NAME.objects.values('PROP1','PROP2').all();

Étape 2:

 result=list(result)  #after getting data from model convert result to list

Étape 3:

 return HttpResponse(json.dumps(result), content_type = "application/json")
4
niran

Pour sérialiser et désérialiser, utilisez les éléments suivants:

from Django.core import serializers

serial = serializers.serialize("json", [obj])
...
# .next() pulls the first object out of the generator
# .object retrieves Django object the object from the DeserializedObject
obj = next(serializers.deserialize("json", serial)).object
3
Zags

Utilisez Sérialiseur Django avec python format,

from Django.core import serializers

qs = SomeModel.objects.all()
serialized_obj = serializers.serialize('python', qs)

Quelle est la différence entre json et python le format?

Le format json renverra le résultat sous la forme str alors que python retournera le résultat est soit list ou OrderedDict

3
JPG

Si vous souhaitez renvoyer le objet unique en tant que réponse json à un client, vous pouvez utiliser cette solution simple:

from Django.forms.models import model_to_dict
from Django.http import JsonResponse

movie = Movie.objects.get(pk=1)
return JsonResponse(model_to_dict(movie))
1
flowfelis

Il ne semble pas que vous puissiez sérialiser une instance, vous devez sérialiser un QuerySet d'un objet.

from Django.core import serializers
from models import *

def getUser(request):
    return HttpResponse(json(Users.objects.filter(id=88)))

Je n’utilise plus la version svn de Django, il est donc possible que ce ne soit pas dans les versions précédentes.

1
Jack M.

que diriez-vous de cette façon:

def ins2dic(obj):
    SubDic = obj.__dict__
    del SubDic['id']
    del SubDic['_state']
return SubDic

ou exclure tout ce que vous ne voulez pas.

1
Reorx
ville = UneVille.objects.get(nom='lihlihlihlih')
....
blablablab
.......

return HttpResponse(simplejson.dumps(ville.__dict__))

Je retourne le dict de mon instance

donc, il retourne quelque chose comme {'field1': value, "field2": value, ....}

1
Jimmy