Django - 根据字段出现的次数进行过滤

时间:2018-04-27 16:06:30

标签: python django django-queryset

我有一个跟踪广告展示次数的模型。

class Impression(models.Model):
    ad = models.ForeignKey(Ad, on_delete=models.CASCADE)
    user_ip = models.CharField(max_length=50, null=True, blank=True)
    clicked = models.BooleanField(default=False)
    time_created = models.DateTimeField(auto_now_add=True)

我想找到展示次数超过1000次的所有user_ip。换句话说,如果user_ip出现在Impression的1000多个实例中。我怎样才能做到这一点?我为此编写了一个函数,但效率非常低且速度慢,因为它会遍历每一次印象。

def check_ip():
    for i in Impression.objects.all():
        if Impression.objects.filter(user_ip=i.user_ip).count() > 1000:
            print(i.user_ip)

2 个答案:

答案 0 :(得分:2)

您应该能够在一个带聚合的查询中执行此操作..可以按以下方式过滤聚合值(如Count()):

from django.db.models import Count

for ip in Impression.objects.values('user_ip').annotate(ipcount=Count('user_ip')).filter(ipcount__gt=1000):
    # do something

答案 1 :(得分:0)

Django查询集有一个annotate()方法,支持您尝试做的事情。

 from django.db.models import Count

 Impression.objects.values('user_ip')\
     .annotate(ip_count=Count('user_ip'))\
     .filter(ip_count__gt=1000)

这将为您提供一个查询集,该查询集返回带有“user_ip”的字典。和' ip_count'用作可迭代的键。

要了解此处发生的事情,您应该查看Django的汇总指南:https://docs.djangoproject.com/en/1.11/topics/db/aggregation/(特别是this section,它解释了annotate如何与{{1}进行互动}})

生成的SQL类似于:

values