Django从m2m到模型按字段注释查询集

时间:2020-08-04 12:44:57

标签: django django-models django-queryset m2m

我有模型BottleType和OrganisationBottleType。 我想通过OrganisationBottleType的“ is_accepted”和“ points”字段注释BottleType查询集。

OrganisationBottleType模型:

PopupMenuButton( color: Colors.red, ...)

假设我具有organization_id和BottleType查询集,因此对于查询集中的每个对象,都需要找到按Bottle_type和organization过滤的OrganisationBottleType,并注释字段“ is_accepted”和“ points”。

(发现过滤后的OrganisationBottleType qs只能从中获取第一个对象,因为假设这两个字段:organization-bottle_type是唯一的)

我的想法是在注释中使用子查询,但我做不到。

我将不胜感激!

1 个答案:

答案 0 :(得分:1)

如果我正确理解您的要求,请针对每种瓶子类型:

  • 找到要点
  • 检查是否被接受。

有两种解决问题的方法:

  1. OrganisationBottleTypeOrganisationBottleType对象的帮助下,获取BottleType查询集并将.prefetch_related()对象与python中Prefetch()中的相应对象进行匹配
  2. BottleTypeOrganisationBottleType的帮助下,用.annotate()中的相应对象注释Subquery()查询集

两个选项的说明如下:

1。将.prefetch_relatedPrefetch对象一起使用

给出:

  • queryset-BottleType查询集
  • organisation_id-所需组织的编号

解决方案:

queryset = queryset.prefetch_related(
    Prefetch(
        'organisation_bottle_types', 
        queryset= OrganisationBottleType.objects.filter(organisation_id=organisation_id)
    )
)

之后,您可以通过以下方式检索所需的数据:

for bottle_type in queryset:
    if bottle_type.organisation_bottle_types.all():
        related_object = bottle_type.organisation_bottle_types.all()[0]
        is_accepted = related_object.is_accepted
        points = related_object.points
    else:
        is_accepted = False
        points = None

2。使用SubQuery

给出:

  • queryset-BottleType查询集
  • organisation_id-所需组织的编号

解决方案:

 organisation_bottle_types = OrganisationBottleType.objects.filter(organisation_id=organisation_id, bottle_type=OuterRef('id'))
queryset = queryset.annotate(
    is_accepted=Subquery(organisation_bottle_types.values('is_accepted')[:1])
).annotate(
    points=Subquery(organisation_bottle_types.values('points')[:1], output_field=BooleanField())
)

您可以这样做之后:

for bottle_type in queryset:
    is_accepted = bottle_type.is_accepted
    points = bottle_type.points

恢复:

就个人而言,我会选择第二种选择,因为它将在数据库级别而不是代码级别执行所有匹配的逻辑。

当您需要匹配整个对象而不仅仅是几个字段(例如问题中的pointsis_accepted)时,第一种选择更好:

相关问题