【问题标题】:Annotate a Django Queryset Using a 'related_name' Across a ManyToMany Relationship (NO 'Count', 'Avg', 'Max', ...)在多对多关系中使用“related_name”注释 Django 查询集(没有“计数”、“平均”、“最大”……)
【发布时间】:2021-12-28 19:13:19
【问题描述】:

我的代码中有类似于以下的模型:

class CompanyProject(models.Model):
    """ This class holds project related information read in from the 'project'
        custom 'manage.py' command.
    """

    project_number = models.IntegerField(blank=False, null=False, unique=True)
    project_worktype = models.CharField(blank=True, max_length=255, null=True)
    created_at = models.DateTimeField(auto_now_add=True, blank=False, null=False)
    updated_at = models.DateTimeField(auto_now=True, blank=False, null=False)
    last_seen = models.DateField(blank=False, null=False)


    def get_project_subtypes(self):
        subtypes = self.project_subtype.all()
        return [ subtype.project_subtype for subtype in subtypes ]

    class Meta:
        ordering = ['project_number']

class CompanySubType(models.Model):
    class CompanySubTypeChoices(models.TextChoices):
        G1A = '1A', _('1A')
        G1B = '1B', _('1B')
        G2A = '2A', _('2A')
        G2B = '2B', _('2B')
        G3A = '3A', _('3A')
        G3B = '3B', _('3B')

    company_project = models.ManyToManyField(CompanyProject, related_name='project_subtype')
    project_subtype = models.CharField(blank=False, choices=CompanySubTypeChoices.choices, max_length=2, null=False)


class ListEntry(models.Model):

    list_project = models.OneToOneField(CompanyProject, on_delete=models.CASCADE, related_name='list_project')
    list_reviewer = models.ForeignKey('auth.User', on_delete=models.CASCADE, related_name='+')

我想返回一组带注释的 ListEntry 对象,这些对象使用ListEntry 项目标识的所有项目子类型的列表进行注释。

最终,我需要能够将此带注释的数据传递给 Django REST Framework 序列化程序,但我需要先让注释像我希望的那样工作。

我的问题是我可以做这样的注释就好了:

list_entry_qs = ListEntry.objects.prefetch_related('list_project', 'list_reviewer').annotate(subtypes=F('list_pmatt__project_subtype__project_subtype')).all()

它工作得很好。我遇到的问题是,如果从该命令返回的查询集重复了 list_entry 对象,如果它有多个 subtype 注释。

例如,如果一个编号为 1234 的项目有两个项目子类型“1A”和“3A”,我会得到两个 list_entry 对象:一个带有 subtype 注释“1A”和一个单独的 list_entry 对象用于与subtype 注释'3A' 相同的项目。

我想为项目 1234 返回一个 SINGLE 对象,该对象具有 subtype 注释“1A”,“2A”,最终将被序列化为 JSON 对象。

必须有一个简单的方法来做到这一点?

【问题讨论】:

    标签: python-3.x django django-rest-framework annotations many-to-many


    【解决方案1】:

    好的,在这上面花了 8 个小时之后,我终于找到了方法:

    from django.contrib.postgres.aggregates.general import ArrayAgg
    
    q = ListEntry.objects.prefetch_related('list_pmatt', 'list_reviewer', 'list_pmatt__project_subtype').annotate(my_subtype=ArrayAgg('list_pmatt__project_subtype__project_subtype'))
    
    >>> q[2].my_subtype
    ['1A', '3A']
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-24
      • 1970-01-01
      • 1970-01-01
      • 2016-03-16
      • 1970-01-01
      • 2011-03-09
      • 1970-01-01
      • 2013-07-15
      相关资源
      最近更新 更多