Há muita documentação sobre como serializar um modelo QuerySet, mas como você serializa para JSON os campos de uma instância de modelo?
Há muita documentação sobre como serializar um modelo QuerySet, mas como você serializa para JSON os campos de uma instância de modelo?
Respostas:
Você pode facilmente usar uma lista para envolver o objeto necessário e é isso que os serializadores do django precisam para serializá-lo corretamente, por exemplo:
from django.core import serializers
# assuming obj is a model instance
serialized_obj = serializers.serialize('json', [ obj, ])
[0]
o final da sua última linha, como sugerido pelo @DavorLucic? E não há necessidade de vírgula à direita na lista (pelo amor ao PEP8;).
Se você estiver lidando com uma lista de instâncias de modelo, o melhor que você pode fazer é usá- serializers.serialize()
lo, ele atenderá perfeitamente à sua necessidade.
No entanto, você deve enfrentar um problema ao tentar serializar um único objeto, não um list
de objetos. Dessa forma, para se livrar de diferentes hacks, basta usar o Django model_to_dict
(se não me engano, também serializers.serialize()
depende):
from django.forms.models import model_to_dict
# assuming obj is your model instance
dict_obj = model_to_dict( obj )
Agora você só precisa de uma json.dumps
ligação direta para serializar para json:
import json
serialized = json.dumps(dict_obj)
É isso aí! :)
datetime
campos. Resolvido desta maneira json.loads(serialize('json', [obj]))[0]
, enquanto serializer édjango.core.serializers.serialize
Para evitar o wrapper de matriz, remova-o antes de retornar a resposta:
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')
Encontrei este post interessante sobre o assunto também:
http://timsaylor.com/convert-django-model-instances-to-dictionaries
Ele usa django.forms.models.model_to_dict, que parece a ferramenta perfeita para o trabalho.
Há uma boa resposta para isso e estou surpreso por não ter sido mencionado. Com algumas linhas, você pode lidar com datas, modelos e tudo mais.
Crie um codificador personalizado que possa manipular modelos:
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)
Agora use-o quando você usa json.dumps
json.dumps(data, cls=ExtendedEncoder)
Agora, modelos, datas e tudo podem ser serializados e não precisam estar em uma matriz ou serializados e não serializados. Tudo o que você tem personalizado pode ser adicionado ao default
método.
Você pode até usar o JsonResponse nativo do Django desta maneira:
from django.http import JsonResponse
JsonResponse(data, encoder=ExtendedEncoder)
``
json.dumps
e json.dump
métodos. Dessa forma, você não precisa alterar o fluxo de trabalho do aplicativo porque usa objetos personalizados ou adiciona outra chamada de método antes da conversão para json. Basta adicionar seu código de conversão no codificador e você está pronto para começar.
Parece que o que você está perguntando envolve serializar a estrutura de dados de uma instância do modelo Django para interoperabilidade. Os outros pôsteres estão corretos: se você desejasse que o formulário serializado fosse usado com um aplicativo python que possa consultar o banco de dados via API do Django, você desejaria serializar um conjunto de consultas com um objeto. Se, por outro lado, o que você precisa é uma maneira de aumentar novamente a instância do modelo em outro lugar sem tocar no banco de dados ou sem usar o Django, então você tem um pouco de trabalho a fazer.
Aqui está o que eu faço:
Primeiro, eu uso demjson
para a conversão. Foi o que encontrei primeiro, mas pode não ser o melhor. Minha implementação depende de um de seus recursos, mas deve haver maneiras semelhantes com outros conversores.
Segundo, implemente um json_equivalent
método em todos os modelos que você possa precisar serializar. Esse é um método mágico demjson
, mas provavelmente é algo em que você vai querer pensar, independentemente da implementação escolhida. A idéia é que você retorne um objeto que seja diretamente conversível em json
(ou seja, uma matriz ou dicionário). Se você realmente deseja fazer isso automaticamente:
def json_equivalent(self):
dictionary = {}
for field in self._meta.get_all_field_names()
dictionary[field] = self.__getattribute__(field)
return dictionary
Isso não será útil para você, a menos que você tenha uma estrutura de dados completamente plana (não ForeignKeys
, apenas números e seqüências de caracteres no banco de dados, etc.). Caso contrário, você deve pensar seriamente sobre a maneira correta de implementar esse método.
Terceiro, ligue demjson.JSON.encode(instance)
e você tem o que deseja.
Se você está perguntando como serializar um único objeto a partir de um modelo e sabe que só obterá um objeto no conjunto de consultas (por exemplo, usando objects.get), use algo como:
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")
o que lhe daria algo da forma:
{"pk": 1, "model": "polls.poll", "fields": {"pub_date": "2013-06-27T02:29:38.284Z", "question": "What's up?"}}
Resolvi esse problema adicionando um método de serialização ao meu modelo:
def toJSON(self):
import simplejson
return simplejson.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))
Aqui está o equivalente detalhado para aqueles que são avessos a 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
é uma lista ordenada de campos de modelo que podem ser acessados a partir de instâncias e do próprio modelo.
Aqui está minha solução para isso, que permite personalizar facilmente o JSON e organizar registros relacionados
Primeiramente implemente um método no modelo. Eu chamo é json
mas você pode chamá-lo como quiser, por exemplo:
class Car(Model):
...
def json(self):
return {
'manufacturer': self.manufacturer.name,
'model': self.model,
'colors': [color.json for color in self.colors.all()],
}
Então, na exibição, eu faço:
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()
Use a lista, resolverá o 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
Etapa 3:
return HttpResponse(json.dumps(result), content_type = "application/json")
Para serializar e desserializar, use o seguinte:
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()
é o que eu precisava para converter uma instância de modelo em JSON.
Documentação .values (): https://docs.djangoproject.com/en/3.0/ref/models/querysets/#values
Exemplo de uso com um modelo chamado Projeto .
Nota: Estou usando o 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])
Resultado de um ID válido:
{
"id": 47,
"title": "Project Name",
"description": "",
"created_at": "2020-01-21T18:13:49.693Z",
}
Se você deseja retornar o objeto de modelo único como uma resposta json para um cliente, é possível fazer esta solução simples:
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 python
formato?O json
formato retornará o resultado como str
considerando python
que retornará o resultado em um list
ouOrderedDict
OrderedDict
, nãodict
Parece que você não pode serializar uma instância, seria necessário serializar um QuerySet de um objeto.
from django.core import serializers
from models import *
def getUser(request):
return HttpResponse(json(Users.objects.filter(id=88)))
Fico sem o svn
lançamento do django, portanto isso pode não estar nas versões anteriores.
ville = UneVille.objects.get(nom='lihlihlihlih')
....
blablablab
.......
return HttpResponse(simplejson.dumps(ville.__dict__))
Volto o ditado da minha instância
portanto, retorna algo como {'campo1': valor, "campo2": valor, ....}
TypeError: <django.db.models.base.ModelState object at 0x7f2b3bf62310> is not JSON serializable
Todas essas respostas foram um pouco hacky em comparação com o que eu esperaria de uma estrutura, o método mais simples, eu acho, de longe, se você estiver usando a estrutura restante:
rep = YourSerializerClass().to_representation(your_instance)
json.dumps(rep)
Isso usa o serializador diretamente, respeitando os campos que você definiu nele, bem como quaisquer associações, etc.
django.core
para fazer isso. Algum motivo específico para não usar serializar o conjunto de consultas?