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

Posted

技术标签:

【中文标题】Django - 如何在序列化的 QuerySet 中包含带注释的结果?【英文标题】:Django - How can you include annotated results in a serialized 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

谢谢!

【问题讨论】:

【参考方案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 仍处于打开状态。

以上是关于Django - 如何在序列化的 QuerySet 中包含带注释的结果?的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 中将 QuerySet 转换为 JSON

在 Django 1.7 中使用 JSONResponse 序列化 QuerySet?

QuerySet 类型的对象不是 JSON 可序列化的 Django

QuerySet 不是 JSON 可序列化的 Django

Django 将日期时间序列化为 QuerySet/Dict 中的 json

QuerySet 对象在 Django Rest Framework 上没有属性“用户”