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

Jas*_*sta 140 python django serialization json django-models

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

xar*_*lis 221

您可以轻松地使用列表来包装所需的对象,这就是django序列化程序正确序列化所需的所有内容,例如:

from django.core import serializers

# assuming obj is a model instance
serialized_obj = serializers.serialize('json', [ obj, ])
Run Code Online (Sandbox Code Playgroud)

  • 如何将所有引用的对象与根对象一起序列化? (9认同)
  • 但作为响应,您需要索引JSON对象的零元素以获取序列化对象.需要注意的事项. (8认同)
  • 难道你不想像 @DavorLucic 建议的那样在最后一行的末尾添加 `[0]` 吗?并且不需要在列表文字中添加尾随逗号(出于对 PEP8 的热爱;)。 (2认同)
  • 这不适合我.Django抛出AttributeError'tuple'对象没有属性'_meta' (2认同)

Pav*_*yak 55

如果您正在处理模型实例列表,您可以做的最好的就是使用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 )
Run Code Online (Sandbox Code Playgroud)

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

import json
serialized = json.dumps(dict_obj)
Run Code Online (Sandbox Code Playgroud)

而已!:)

  • 这与UUID字段失败,否则应该清楚 (4认同)
  • 失败,带有“ datetime”字段。通过序列化器为django.core.serializers.serialize的json.loads(serialize('json',[obj]))[0]这样解决 (2认同)

Jul*_*ian 41

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

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')
Run Code Online (Sandbox Code Playgroud)

我在这个主题上发现了这篇有趣的帖子:

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

它使用django.forms.models.model_to_dict,它看起来像是工作的完美工具.

  • 如果这是在django中序列化单个模型的最佳方法,那么这很糟糕,因为不需要反序列化json并将其序列化. (6认同)
  • 隐藏恐怖不是问题,甚至可能不是这个解决方案;令我惊讶的是,这是 django 最好的实现方式。 (3认同)

kag*_*ick 12

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

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

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)
Run Code Online (Sandbox Code Playgroud)

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

json.dumps(data, cls=ExtendedEncoder)
Run Code Online (Sandbox Code Playgroud)

现在,模型,日期和所有内容都可以序列化,而不必放在数组中或序列化和非序列化。

  • 该解决方案简单而优雅。该编码器可以与json.dumps和json.dump方法一起使用。这样,您无需更改应用程序的工作流程,因为您可以使用自定义对象或在转换为json之前添加另一个方法调用。只需将您的转换代码添加到编码器中,即可开始使用。 (2认同)

Dav*_*ger 10

听起来你要问的是为了互操作性而序列化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
Run Code Online (Sandbox Code Playgroud)

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

第三,打电话demjson.JSON.encode(instance),你有你想要的.


小智 8

如果您正在询问如何从模型中序列化单个对象,并且您知道您将只在查询集中获取一个对象(例如,使用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")
Run Code Online (Sandbox Code Playgroud)

这会给你一些形式:

{"pk": 1, "model": "polls.poll", "fields": {"pub_date": "2013-06-27T02:29:38.284Z", "question": "What's up?"}}
Run Code Online (Sandbox Code Playgroud)


小智 6

如果您想将单个模型对象作为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))
Run Code Online (Sandbox Code Playgroud)


dav*_*ers 5

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

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

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

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)
Run Code Online (Sandbox Code Playgroud)

_meta.fields 是模型字段的有序列表,可以从实例和模型本身进行访问。

  • 尽管乍一看这个主意似乎不错,但应该指出使用这种方法会产生后果。您将一个特定的序列化输出绑定到模型。 (3认同)

Dan*_*anH 5

这是我的解决方案,可让您轻松自定义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()],
        }
Run Code Online (Sandbox Code Playgroud)

然后在视图中我这样做:

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


Ric*_*ard 5

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

.values() 文档:https ://docs.djangoproject.com/en/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])
Run Code Online (Sandbox Code Playgroud)

来自有效 ID 的结果:

{
    "id": 47,
    "title": "Project Name",
    "description": "",
    "created_at": "2020-01-21T18:13:49.693Z",
}
Run Code Online (Sandbox Code Playgroud)