如何在Django中序列化模型实例?

问题:如何在Django中序列化模型实例?

关于如何序列化模型QuerySet的文档很多,但是如何将模型实例的字段序列化为JSON?

There is a lot of documentation on how to serialize a Model QuerySet but how do you just serialize to JSON the fields of a Model Instance?


回答 0

您可以轻松地使用列表来包装所需的对象,而这正是Django序列化程序正确地序列化它所需要的,例如:

from django.core import serializers

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

You can easily use a list to wrap the required object and that’s all what django serializers need to correctly serialize it, eg.:

from django.core import serializers

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

回答 1

如果您要处理的模型实例列表是您最好的选择serializers.serialize(),那么它会完全满足您的需求。

但是,您要尝试序列化单个对象而不是对象的对象时会遇到问题list。这样,为了摆脱各种黑客攻击,只需使用Django即可model_to_dict(如果我没记错的serializers.serialize()话,也要依赖它):

from django.forms.models import model_to_dict

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

现在,您只需要直接json.dumps调用即可将其序列化为json:

import json
serialized = json.dumps(dict_obj)

而已!:)

If you’re dealing with a list of model instances the best you can do is using serializers.serialize(), it gonna fit your need perfectly.

However, you are to face an issue with trying to serialize a single object, not a list of objects. That way, in order to get rid of different hacks, just use Django’s model_to_dict (if I’m not mistaken, serializers.serialize() relies on it, too):

from django.forms.models import model_to_dict

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

You now just need one straight json.dumps call to serialize it to json:

import json
serialized = json.dumps(dict_obj)

That’s it! :)


回答 2

为了避免数组包装,请在返回响应之前将其删除:

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')

我也发现了关于这个主题的这篇有趣的文章:

http://timsaylor.com/convert-django-model-instances-to-dictionaries

它使用django.forms.models.model_to_dict,它看起来像是完成这项工作的理想工具。

To avoid the array wrapper, remove it before you return the response:

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')

I found this interesting post on the subject too:

http://timsaylor.com/convert-django-model-instances-to-dictionaries

It uses django.forms.models.model_to_dict, which looks like the perfect tool for the job.


回答 3

对此有一个很好的答案,我很惊讶没有提到它。仅需几行,您就可以处理日期,模型以及其他所有内容。

制作一个可以处理模型的自定义编码器:

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)

现在在使用json.dumps时使用它

json.dumps(data, cls=ExtendedEncoder)

现在,模型,日期和所有内容都可以序列化,而不必放在数组中或序列化和非序列化。您拥有的所有自定义内容都可以添加到default方法中。

您甚至可以通过以下方式使用Django的本地JsonResponse:

from django.http import JsonResponse

JsonResponse(data, encoder=ExtendedEncoder)
``

There is a good answer for this and I’m surprised it hasn’t been mentioned. With a few lines you can handle dates, models, and everything else.

Make a custom encoder that can handle models:

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)

Now use it when you use json.dumps

json.dumps(data, cls=ExtendedEncoder)

Now models, dates and everything can be serialized and it doesn’t have to be in an array or serialized and unserialized. Anything you have that is custom can just be added to the default method.

You can even use Django’s native JsonResponse this way:

from django.http import JsonResponse

JsonResponse(data, encoder=ExtendedEncoder)

回答 4

听起来您要问的是涉及序列化Django模型实例的数据结构以实现互操作性。其他张贴者是正确的:如果您希望将序列化表格与可以通过Django api查询数据库的python应用程序一起使用,则需要使用一个对象序列化一个查询集。另一方面,如果您需要的是在不接触数据库或不使用Django的情况下在其他地方重新添加模型实例的方法,则您需要做一些工作。

这是我的工作:

首先,我demjson用于转换。碰巧是我首先发现的,但可能不是最好的。我的实现方式取决于其功能之一,但其他转换器也应采用类似的方式。

其次,json_equivalent在可能需要序列化的所有模型上实现一个方法。这是的神奇方法demjson,但是无论您选择哪种实现,都可能要考虑一下。这个想法是,您返回一个可以直接转换为的对象json(即数组或字典)。如果您真的想自动执行此操作:

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

除非您具有完全平坦的数据结构(否ForeignKeys,数据库中只有数字和字符串,等等),否则这对您没有帮助。否则,您应该认真考虑实现此方法的正确方法。

第三,打电话给demjson.JSON.encode(instance)您,您便拥有了想要的东西。

It sounds like what you’re asking about involves serializing the data structure of a Django model instance for interoperability. The other posters are correct: if you wanted the serialized form to be used with a python application that can query the database via Django’s api, then you would wan to serialize a queryset with one object. If, on the other hand, what you need is a way to re-inflate the model instance somewhere else without touching the database or without using Django, then you have a little bit of work to do.

Here’s what I do:

First, I use demjson for the conversion. It happened to be what I found first, but it might not be the best. My implementation depends on one of its features, but there should be similar ways with other converters.

Second, implement a json_equivalent method on all models that you might need serialized. This is a magic method for demjson, but it’s probably something you’re going to want to think about no matter what implementation you choose. The idea is that you return an object that is directly convertible to json (i.e. an array or dictionary). If you really want to do this automatically:

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

This will not be helpful to you unless you have a completely flat data structure (no ForeignKeys, only numbers and strings in the database, etc.). Otherwise, you should seriously think about the right way to implement this method.

Third, call demjson.JSON.encode(instance) and you have what you want.


回答 5

如果您要问如何从模型中序列化一个对象,并且知道仅要在查询集中获取一个对象(例如,使用objects.get),则可以使用以下方法:

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")

这将使您具有以下形式:

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

If you’re asking how to serialize a single object from a model and you know you’re only going to get one object in the queryset (for instance, using objects.get), then use something like:

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")

which would get you something of the form:

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

回答 6

我通过向模型添加序列化方法解决了这个问题:

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

这是那些讨厌单线的冗长等效项:

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 是模型字段的有序列表,可以从实例和模型本身进行访问。

I solved this problem by adding a serialization method to my model:

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

Here’s the verbose equivalent for those averse to 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 is an ordered list of model fields which can be accessed from instances and from the model itself.


回答 7

这是我的解决方案,可让您轻松自定义JSON并组织相关记录

首先在模型上实现一种方法。我称是,json但是您可以随便叫它,例如:

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

然后在视图中我这样做:

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

Here’s my solution for this, which allows you to easily customize the JSON as well as organize related records

Firstly implement a method on the model. I call is json but you can call it whatever you like, e.g.:

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

Then in the view I do:

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

回答 8

使用清单,将解决问题

第1步:

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

第2步:

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

第三步:

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

Use list, it will solve problem

Step1:

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

Step2:

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

Step3:

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

回答 9

要序列化和反序列化,请使用以下命令:

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

To serialize and deserialze, use the following:

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

回答 10

.values() 我需要将模型实例转换为JSON。

.values()文档:https ://docs.djangoproject.com/zh/3.0/ref/models/querysets/#values

名为Project的模型的示例用法。

注意:我正在使用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])

有效ID的结果:

{
    "id": 47,
    "title": "Project Name",
    "description": "",
    "created_at": "2020-01-21T18:13:49.693Z",
}

.values() is what I needed to convert a model instance to JSON.

.values() documentation: https://docs.djangoproject.com/en/3.0/ref/models/querysets/#values

Example usage with a model called Project.

Note: I’m using 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])

Result from a valid id:

{
    "id": 47,
    "title": "Project Name",
    "description": "",
    "created_at": "2020-01-21T18:13:49.693Z",
}

回答 11

如果要将单个模型对象作为json响应返回给客户端,则可以执行以下简单解决方案:

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))

If you want to return the single model object as a json response to a client, you can do this simple solution:

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))

回答 12

使用Django序列化器python格式,

from django.core import serializers

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

jsonpython格式有什么区别?

json格式将返回的结果str,而python将在返回的结果要么listOrderedDict

Use Django Serializer with python format,

from django.core import serializers

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

What’s difference between json and python format?

The json format will return the result as str whereas python will return the result in either list or OrderedDict


回答 13

似乎您不能序列化一个实例,而必须序列化一个对象的QuerySet。

from django.core import serializers
from models import *

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

我用完了svndjango发行版,因此在较早的版本中可能不存在。

It doesn’t seem you can serialize an instance, you’d have to serialize a QuerySet of one object.

from django.core import serializers
from models import *

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

I run out of the svn release of django, so this may not be in earlier versions.


回答 14

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

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

我返回我的实例的命令

因此它返回的内容类似于{‘field1’:value,“ field2”:value,….}

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

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

I return the dict of my instance

so it return something like {‘field1’:value,”field2″:value,….}


回答 15

这样呢:

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

或排除您不想要的任何东西。

how about this way:

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

or exclude anything you don’t want.


回答 16

与我希望从框架(最简单的方法)相比,所有这些答案都有些棘手,如果您使用其余框架,我认为到目前为止,这是最简单的方法:

rep = YourSerializerClass().to_representation(your_instance)
json.dumps(rep)

这将直接使用Serializer,同时尊重您在其上定义的字段以及任何关联等。

All of these answers were a little hacky compared to what I would expect from a framework, the simplest method, I think by far, if you are using the rest framework:

rep = YourSerializerClass().to_representation(your_instance)
json.dumps(rep)

This uses the Serializer directly, respecting the fields you’ve defined on it, as well as any associations, etc.