【问题标题】:Can I add a custom method to a Django queryset?我可以向 Django 查询集添加自定义方法吗?
【发布时间】:2020-01-15 21:21:33
【问题描述】:

假设我有两个模型,一对多的关系:

from django.db import models

class Quantity(models.Model):
    name = models.CharField(max_length=64)


class Measurement(models.Model):
    value = models.FloatField()
    date = models.DateField()
    quantity = models.ForeignKeyField(Quantity, on_delete=models.CASCADE)

我还做了一些记录...

weight = Quantity.objects.create(name="Body Weight in kg")
Measurement.objects.create(value=80, date="2020-01-01", quantity=weight)
Measurement.objects.create(value=81, date="2020-01-02", quantity=weight)
Measurement.objects.create(value=80.6, date="2020-01-03", quantity=weight)
Measurement.objects.create(value=80.1, date="2020-01-04", quantity=weight)
Measurement.objects.create(value=79.5, date="2020-01-05", quantity=weight)
Measurement.objects.create(value=81, date="2020-01-06", quantity=weight)
Measurement.objects.create(value=81, date="2020-01-07", quantity=weight)

无论如何我可以像这样从查询集中计算指标...

weight.measurement_set.all().average()
weight.measurement_set.filter(date__gt="2020-01-04").average()
weight.measurement_set.all().sum()

...我在某处定义了相关方法...

def average(queryset):
   return sum([m.value for m in queryset]) / queryset.count())

def average(queryset):
   return sum([m.value for m in queryset])

我从 2011 年开始阅读 this post,但答案似乎有点过时并且似乎不起作用。我目前正在使用 django 2.2。

【问题讨论】:

  • 是的,尽管您可以简单地用.aggregate(r=Avg('value'))['r'] 计算平均值。

标签: django django-models django-queryset


【解决方案1】:

是的,你可以继承QuerySet类,例如:

from django.db.models import Avg, Sum
from django.db.models.query import QuerySet

class CustomQuerySet(QuerySet):

    def average(self):
        return self.aggregate(_total=Avg('value'))['_total']

    def sum(self):
        return self.aggregate(_total=Sum('value'))['_total']

请注意,在此处创建 .aggregate(..) calls [Django-doc] 更有效,因为它们将在 数据库 而不是 Django/Python 级别运行聚合。

接下来我们可以使用CustomQuerySet_queryset_class 制作一个自定义管理器:

from django.db import models

class CustomManager(models.Manager):
    _queryset_class = CustomQuerySet

然后我们可以为我们的模型添加一个管理器:

class Measurement(models.Model):
    value = models.FloatField()
    date = models.DateField()
    quantity = models.ForeignKeyField(Quantity, on_delete=models.CASCADE)

    objects = CustomManager()

【讨论】:

  • 非常感谢 - 这正是我一直在寻找的。​​span>
猜你喜欢
  • 2011-06-02
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 2010-11-03
相关资源
最近更新 更多