C'è molta documentazione su come serializzare un Model QuerySet ma come si fa a serializzare su JSON i campi di un'istanza del modello?
C'è molta documentazione su come serializzare un Model QuerySet ma come si fa a serializzare su JSON i campi di un'istanza del modello?
Risposte:
Puoi facilmente usare un elenco per racchiudere l'oggetto richiesto ed è tutto ciò che serve ai serializzatori django per serializzarlo correttamente, ad es .:
from django.core import serializers
# assuming obj is a model instance
serialized_obj = serializers.serialize('json', [ obj, ])
[0]
alla fine dell'ultima riga, come suggerito da @DavorLucic? E non c'è bisogno di trascinare la virgola nel tuo elenco letterale (per l'amore di PEP8;).
Se hai a che fare con un elenco di istanze del modello che il meglio che puoi fare è usare serializers.serialize()
, si adatterà perfettamente alle tue esigenze.
Tuttavia, devi affrontare un problema con il tentativo di serializzare un singolo oggetto, non uno list
di oggetti. In questo modo, per sbarazzarti di diversi hack, usa semplicemente Django model_to_dict
(se non sbaglio, fai serializers.serialize()
affidamento anche su di esso):
from django.forms.models import model_to_dict
# assuming obj is your model instance
dict_obj = model_to_dict( obj )
Ora hai solo bisogno di una json.dumps
chiamata diretta per serializzare su json:
import json
serialized = json.dumps(dict_obj)
Questo è tutto! :)
datetime
campi. Risolto in questo modo json.loads(serialize('json', [obj]))[0]
mentre il serializzatore èdjango.core.serializers.serialize
Per evitare il wrapper di array, rimuoverlo prima di restituire la risposta:
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')
Ho trovato questo interessante post anche sull'argomento:
http://timsaylor.com/convert-django-model-instances-to-dictionaries
Utilizza django.forms.models.model_to_dict, che sembra lo strumento perfetto per il lavoro.
C'è una buona risposta per questo e sono sorpreso che non sia stato menzionato. Con poche righe puoi gestire date, modelli e tutto il resto.
Crea un codificatore personalizzato in grado di gestire i modelli:
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)
Ora usalo quando usi json.dumps
json.dumps(data, cls=ExtendedEncoder)
Ora i modelli, le date e tutto possono essere serializzati e non devono essere in un array o serializzati e non serializzati. Tutto ciò che hai personalizzato può essere semplicemente aggiunto al default
metodo.
Puoi anche usare JsonResponse nativo di Django in questo modo:
from django.http import JsonResponse
JsonResponse(data, encoder=ExtendedEncoder)
``
json.dumps
e json.dump
metodi. In questo modo non è necessario modificare il flusso di lavoro dell'applicazione poiché si utilizzano oggetti personalizzati o si aggiunge un'altra chiamata di metodo prima della conversione in json. Aggiungi il tuo codice di conversione nel codificatore e sei pronto per partire.
Sembra che ciò che stai chiedendo riguardi la serializzazione della struttura dei dati di un'istanza del modello Django per l'interoperabilità. Gli altri poster sono corretti: se si desidera che il modulo serializzato venga utilizzato con un'applicazione Python in grado di eseguire query sul database tramite l'API di Django, quindi si vorrebbe serializzare un queryset con un oggetto. Se, d'altra parte, quello che ti serve è un modo per gonfiare nuovamente l'istanza del modello da qualche altra parte senza toccare il database o senza usare Django, allora hai un po 'di lavoro da fare.
Ecco cosa faccio:
In primo luogo, io uso demjson
per la conversione. È successo per caso quello che ho trovato per primo, ma potrebbe non essere il migliore. La mia implementazione dipende da una delle sue caratteristiche, ma ci dovrebbero essere modi simili con altri convertitori.
In secondo luogo, implementare un json_equivalent
metodo su tutti i modelli che potrebbero essere necessari serializzati. Questo è un metodo magico per demjson
, ma probabilmente è qualcosa a cui vorresti pensare, indipendentemente dall'implementazione che scegli. L'idea è di restituire un oggetto direttamente convertibile json
(ovvero un array o un dizionario). Se vuoi davvero farlo automaticamente:
def json_equivalent(self):
dictionary = {}
for field in self._meta.get_all_field_names()
dictionary[field] = self.__getattribute__(field)
return dictionary
Questo non ti sarà utile a meno che tu non abbia una struttura di dati completamente piatta (no ForeignKeys
, solo numeri e stringhe nel database, ecc.). Altrimenti, dovresti pensare seriamente al modo giusto di implementare questo metodo.
In terzo luogo, chiama demjson.JSON.encode(instance)
e hai quello che vuoi.
Se stai chiedendo come serializzare un singolo oggetto da un modello e sai che otterrai un solo oggetto nel queryset (ad esempio, usando objects.get), usa qualcosa come:
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")
che ti darebbe qualcosa del modulo:
{"pk": 1, "model": "polls.poll", "fields": {"pub_date": "2013-06-27T02:29:38.284Z", "question": "What's up?"}}
Ho risolto questo problema aggiungendo un metodo di serializzazione al mio modello:
def toJSON(self):
import simplejson
return simplejson.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))
Ecco l'equivalente dettagliato per quelli avversi a una linea:
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
è un elenco ordinato di campi modello a cui è possibile accedere dalle istanze e dal modello stesso.
Ecco la mia soluzione per questo, che ti consente di personalizzare facilmente JSON e di organizzare i record correlati
Innanzitutto implementare un metodo sul modello. Io chiamo è json
ma puoi chiamarlo come preferisci, ad esempio:
class Car(Model):
...
def json(self):
return {
'manufacturer': self.manufacturer.name,
'model': self.model,
'colors': [color.json for color in self.colors.all()],
}
Quindi nella vista lo faccio:
data = [car.json for car in Car.objects.all()]
return HttpResponse(json.dumps(data), content_type='application/json; charset=UTF-8', status=status)
car.json()
Usa l'elenco, risolverà il problema
Passo 1:
result=YOUR_MODELE_NAME.objects.values('PROP1','PROP2').all();
Passo 2:
result=list(result) #after getting data from model convert result to list
Fase 3:
return HttpResponse(json.dumps(result), content_type = "application/json")
Per serializzare e deserializzare, utilizzare quanto segue:
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
.values()
è ciò di cui avevo bisogno per convertire un'istanza del modello in JSON.
Documentazione .values (): https://docs.djangoproject.com/en/3.0/ref/models/querysets/#values
Esempio di utilizzo con un modello chiamato Progetto .
Nota: sto usando Django Rest Framework
@csrf_exempt
@api_view(["GET"])
def get_project(request):
id = request.query_params['id']
data = Project.objects.filter(id=id).values()
if len(data) == 0:
return JsonResponse(status=404, data={'message': 'Project with id {} not found.'.format(id)})
return JsonResponse(data[0])
Risultato da un ID valido:
{
"id": 47,
"title": "Project Name",
"description": "",
"created_at": "2020-01-21T18:13:49.693Z",
}
Se si desidera restituire l' oggetto modello singolo come risposta json a un client, è possibile eseguire questa semplice soluzione:
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))
python
formato,from django.core import serializers
qs = SomeModel.objects.all()
serialized_obj = serializers.serialize('python', qs)
json
e il python
formato?Il json
formato restituirà il risultato mentre str
mentre python
restituirà il risultato in uno list
oOrderedDict
OrderedDict
, nondict
Non sembra che tu possa serializzare un'istanza, dovresti serializzare un QuerySet di un oggetto.
from django.core import serializers
from models import *
def getUser(request):
return HttpResponse(json(Users.objects.filter(id=88)))
Ho finito il svn
rilascio di Django, quindi potrebbe non essere disponibile nelle versioni precedenti.
ville = UneVille.objects.get(nom='lihlihlihlih')
....
blablablab
.......
return HttpResponse(simplejson.dumps(ville.__dict__))
Restituisco il dict della mia istanza
quindi restituisce qualcosa come {'field1': value, "field2": value, ....}
TypeError: <django.db.models.base.ModelState object at 0x7f2b3bf62310> is not JSON serializable
Tutte queste risposte sono state un po 'confuse rispetto a quello che mi aspetterei da un framework, il metodo più semplice, penso di gran lunga, se stai usando il framework del resto:
rep = YourSerializerClass().to_representation(your_instance)
json.dumps(rep)
Questo utilizza direttamente il serializzatore, rispettando i campi che hai definito su di esso, nonché eventuali associazioni, ecc.
django.core
per farlo. Qualche motivo particolare per non utilizzare serializzare il queryset?