【问题标题】:Django Many2Many AnnotationDjango Many2Many 注释
【发布时间】:2018-07-30 07:11:03
【问题描述】:

我有两个 Django 表:AB。它们之间存在many2many关系,写在表A中。

我遇到的问题是,当我将其作为 API 提供并将对象显示为 A.objects.all().values() 时,B 的值不会显示。

我想用many2many关系的ids注释Django表A,这样我可以在我做A.objects.all().values()的时候拉它们,得到A.B_ids=['134','141','1414']

例如,这可以,但我有一种直觉,每当我在 Django 中进行迭代时,它可以做得更快:

@api_view(['GET'])
def pull_tasks():
    a_values = list(A.objects.all().values())

    for a in a_values:
        a['b_values'] = (A.objects.get(id=a['id']).b.all().values())
    return Response(a_values, status=status.HTTP_200_OK)

【问题讨论】:

  • 我觉得使用.values() 很奇怪。这通常仅用于对 cme​​ts 执行特定选择。但是,我认为您在错误的层解决了问题:这通常是使用序列化程序的地方。
  • 请参见此处的示例:stackoverflow.com/a/33439544/67579。你能分享一下 API 的当前方法吗?
  • 检查问题的新编辑。
  • 编辑没有帮助。这不是值的工作,而是序列化程序的工作。

标签: python django


【解决方案1】:

您可以通过使用.values_list('id', flat=True) 并在多对多关系的查询中处理B 模型来构建快速修复。例如:

@api_view(['GET'])
def pull_tasks():
    a_values = list(A.objects.all().values())

    for a in a_values:
        a['b_values'] = list(B.objects.filter(a_id=a['id']).values_list('id', flat=True))
    return Response(a_values, status=status.HTTP_200_OK)

所以现在我们为相关的B 元素构建一个简单的 id 列表,但这不是很有效,因为我们为 每个 A 对象执行提取,这可以很容易地变得非常昂贵。

你在这里基本上做的是写一个序列化器。但是 Django 已经通过编写一个序列化程序来支持这一点:使用 Django REST 框架。例如:

from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField

class ASerializer(ModelSerializer):
    skills_ids = PrimaryKeyRelatedField(
        many=True,
        read_only=False,
        queryset=B.objects.all(),
        source='b'
    )

    class Meta:
        model = A

然后,您可以例如用作视图:

@api_view(['GET'])
def pull_tasks():
    ser = ASerializer(A.objects.prefetch_related('B'), many=True)
    return Response(ser.data, status=status.HTTP_200_OK)

通过使用prefetch_related(..),我们将在另一个查询中获取所有相关的Bs,而不是每个A 对象查询一次。

【讨论】:

  • 那个序列化器就是我要找的。感谢您提供详细的示例!
猜你喜欢
  • 2022-12-07
  • 2013-11-05
  • 1970-01-01
  • 1970-01-01
  • 2011-10-23
  • 2015-12-09
  • 2016-11-18
  • 2015-10-21
  • 1970-01-01
相关资源
最近更新 更多