【问题标题】:Filter based on a amount of object returned by another query in Django根据 Django 中另一个查询返回的对象数量进行过滤
【发布时间】:2017-12-23 09:45:30
【问题描述】:

我的模型PaintingHit 中有两个类。

class Painting(models.Model):
    objectNumber = models.CharField(max_length=128)

class Hit(models.Model):
    painting = models.ForeignKey(Painting)

这样,每幅画可以连接多张点击,但每张点击只能连接一张画。

我希望选择每幅与 3 次或更少点击次数相关的画作。我该怎么做?

可能的解决方案:

我想我可以做一些 for 循环...

for painting in Painting.objects.all():
    if len(Hit.objects.filter(painting=painting)) > 4:
        # and then append it to a list or something

...但我认为我可以应用一些我似乎找不到的本机过滤器。或者我可以在Painting 中添加一个字段来计算与之相关的点击次数,但这似乎不合逻辑。

【问题讨论】:

    标签: django django-queryset


    【解决方案1】:

    您可以为此使用select_related。为此,您必须为您声明一个related_name Hit 模型

    class Hit(models.Model):
        painting = models.ForeignKey(Painting, related_name='paintings')
    

    然后在绘画模型上使用select相关

    Painting.objects.all().select_related('painting')
    

    这将为您提供查询集。现在您可以应用任何操作,例如lencount,但现在无需循环。对于您的情况,您可以链接任何注释或过滤器来计算点击次数。

    注意:如果您有 ManyToMany 字段而不是外键字段,那么 prefetch_related 就可以了。

    【讨论】:

    • select_related 仅适用于 onetoone 和 foreignkeyfield。如果你有 manytomany 字段,你必须去 prefetch_related
    • 我似乎无法正确理解。我运行Painting.objects.all().prefetch_related('paintings'),它返回一个AttributeError: Cannot find 'paintings' on Painting object, 'paintings' is an invalid parameter to prefetch_related()
    • 为什么预取相关?你有外键所以你必须使用 select_related
    • 我也在尝试多对多字段:painting = models.ManyToManyField(Painting,blank=True,related_name='paintings')
    【解决方案2】:

    您需要查看查询集注释。您可以注释每幅画的点击次数,然后根据点击次数过滤绘画 (docs)。

    from django.db.models import Count
    
    Painting.objects.annotate(num_hits=Count('hit')).filter(num_hits__lte=3)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      • 2021-03-01
      • 2019-09-15
      • 2012-08-19
      • 2020-09-30
      • 2023-03-12
      相关资源
      最近更新 更多