【问题标题】:How to serialize to JSON a list of model objects in django/python如何将 django/python 中的模型对象列表序列化为 JSON
【发布时间】:2012-10-13 10:06:44
【问题描述】:

我正在尝试序列化定义为的模型对象列表:

class AnalysisInput(models.Model):
    input_user = models.CharField(max_length=45)
    input_title = models.CharField(max_length=45)
    input_date = models.DateTimeField()
    input_link = models.CharField(max_length=100)

我为 json.dumps() 编写了一个自定义序列化器(编码器):

class AnalysisInputEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, AnalysisInput):
            return { "input_id" : obj.id,
                    "input_user" : obj.input_user,
                    "input_title" : obj.input_title,
                    "input_date" : obj.input_date.isoformat(),
                    "input_link" : obj.input_link }
        return json.JSONEncoder.default(self, obj)

当我只序列化一个对象时,我可以做到。当我尝试序列化我得到的对象列表时

[ objects..] is not JSON serializable

我搜索了但我没有找到工作的地方。我正在考虑为模型对象列表编写一个自定义序列化程序。

【问题讨论】:

    标签: python json django django-models


    【解决方案1】:

    自定义编码器不会被递归调用。实际上你最好使用自定义编码器,而是在序列化之前将你的对象转换为简单的python类型。

    您可以在模型中添加 as_json 或类似名称的方法,并在每次需要 JSON 结果时调用:

    class AnalysisInput(models.Model):
        input_user = models.CharField(max_length=45)
        input_title = models.CharField(max_length=45)
        input_date = models.DateTimeField()
        input_link = models.CharField(max_length=100)
    
        def as_json(self):
            return dict(
                input_id=self.id, input_user=self.input_user,
                input_title=self.input_title, 
                input_date=self.input_date.isoformat(),
                input_link=self.input_link)
    

    那么在你看来:

    # one result
    return HttpResponse(json.dumps(result.as_json()), content_type="application/json")
    
    # a list of results
    results = [ob.as_json() for ob in resultset]
    return HttpResponse(json.dumps(results), content_type="application/json")
    

    【讨论】:

    • 它工作得很好,完美无瑕:).. 请问我为什么不应该使用自定义编码器?
    • @Francesco:您必须编写完全递归所有列表、元组和映射的东西才能找到您的模型对象。但是,在您的视图中,您已经知道模型对象的确切位置,从而更容易维护代码。当然,您可以结合这两种技术;以pyramid's JSON renderer supports __json__ methods on results 为例。
    • 当我尝试时,我得到了这个异常> unbound method as_json() must be called with Category instance as first argument
    • @AlexJolig:你在模型的实际实例上调用它,而不是模型本身。
    • 看起来很棒!方法名称/签名是否应该是 as_dict(self),因为它并没有真正返回 json...
    【解决方案2】:

    我发现序列化 Django 模型的最佳方法是使用 django.core.serializers 将模型列表序列化为 JSON、XML 或 YAML。无需自定义序列化代码!文档在这里:https://docs.djangoproject.com/en/dev/topics/serialization/

    这是我的实现:

    lead/models.py:

    from django.db import models
    
    class Lead(models.Model):
        name = models.CharField(max_length=50)
        email = models.CharField(max_length=256)
        phone = models.CharField(max_length=20)
        twitter_handle = models.CharField(max_length=20)
        github_handle = models.CharField(max_length=20)
    

    lead/views.py:

    from django.http import HttpResponse
    from django.core import serializers
    from lead.models import Lead
    
    def index(request):
        leads_as_json = serializers.serialize('json', Lead.objects.all())
        return HttpResponse(leads_as_json, content_type='application/json')
    

    最终结果:

    [{"pk": 1, "model": "lead.lead", "fields": {"twitter_handle": "johndoe", "name": "John Doe", "phone": "1(234)567-8910", "email": "john@doe.com", "github_handle": "johndoe"}}]
    

    【讨论】:

    • 如何自定义响应?
    【解决方案3】:

    最简单的解决方案:

    def index(request):
        data = serializers.serialize('json', Product.objects.all())
        return HttpResponse(data, content_type='application/json')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-30
      • 1970-01-01
      • 2017-06-20
      • 2019-05-17
      • 1970-01-01
      • 2016-12-22
      • 2017-09-03
      • 2011-03-01
      相关资源
      最近更新 更多