【问题标题】:Django - How can you include annotated results in a serialized QuerySet?Django - 如何在序列化的 QuerySet 中包含带注释的结果?
【发布时间】:2014-10-13 14:20:33
【问题描述】:

如何在序列化的 QuerySet 中包含带注释的结果?

data = serializer.serialize(Books.objects.filter(publisher__id=id).annotate(num_books=Count('related_books')), use_natural_keys=True)

但是,键/值对 {'num_books': number} 不包含在 json 结果中。

我一直在互联网上搜索类似的问题,但没有找到适合我的解决方案。

这是一个类似的案例:http://python.6.x6.nabble.com/How-can-you-include-annotated-results-in-a-serialized-QuerySet-td67238.html

谢谢!

【问题讨论】:

    标签: python json django annotate serialization


    【解决方案1】:

    我做了一些研究,发现serializer.serialize只能序列化查询集,而注解只是为查询集的每个对象添加一个属性,因此当您尝试序列化查询时,不会显示带注解的字段。这是我的实现方式:

    from django.core.serializers.json import DjangoJSONEncoder
    
    books = Books.objects.filter(publisher__id=id).annotate(num_books=Count('related_books')).values()
    json_data = json.dumps(list(books), cls=DjangoJSONEncoder)
    

    【讨论】:

      【解决方案2】:

      this post 所示,您可以在您的 Serializer 中使用 SerializerMethodField:

      class BooksSerializer(serializers.ModelSerializer):
      
        num_books = serializers.SerializerMethodField()
      
        def get_num_books(self, obj):
          try:
              return obj.num_books
          except:
              return None
      

      它将序列化带注释的值(只读)

      【讨论】:

      • 这应该是公认的答案,它可以完美运行!
      • 这是正确答案。 A也可以在serializers.SerializerMethodField() 方法中执行相同的注释逻辑,但如果已经在queryset 上完成,则不宜使用以避免重复代码。
      【解决方案3】:

      要从特定列中获取计数,您必须通过values 方法声明它们

      >>>> Books.objects.filter(publisher__id=id).values('<group by field>').annotate(num_books=Count('related_books'))
      [{'num_books': 1, '<group by field>': X}]
      

      【讨论】:

      • 我的计数是正确的,问题是序列化程序类。但是感谢您的帮助!
      【解决方案4】:

      根据链接,几个月前this 已通过拉取请求 (https://github.com/django/django/pull/1176) 解决。

      您需要将num_books 添加为属性:

      class Publisher():
          ....
      
          @property
          def num_books(self):
              return some_way_to_count('related_books')
      

      然后这样称呼它:

      data = serializer.serialize(Books.objects.filter(publisher__id=id)), use_natural_keys=True, extra=['num_books'])
      

      我不太确定确切的语法,因为我不太使用序列化程序。

      【讨论】:

      • 感谢您的帮助,但我无法让它工作。另外,如果我的模型是 Django 内置的用户 (from django.contrib.auth.models import User) 你怎么做?
      • 截至 2017 年 10 月,pull request 已关闭,未合并,ticket 仍处于打开状态。
      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 2019-08-03
      • 2011-06-22
      • 1970-01-01
      • 2015-10-29
      • 1970-01-01
      • 2023-03-30
      • 2019-12-19
      相关资源
      最近更新 更多