Django自定义预取和条件注释
我使用自定义预取对象仅获取一些相关对象,例如:Django自定义预取和条件注释,django,django-queryset,Django,Django Queryset,我使用自定义预取对象仅获取一些相关对象,例如: unreleased_prefetch = Prefetch("chants", Chant.objects.with_audio()) teams = Team.objects.public().prefetch_related(unreleased_prefetch) 这很有效,但我还想知道这些对象的数量,并根据它们进行过滤。我很高兴目前可以使用queryset作为参数来预取对象(因为我大量使用自定义queryset/Manager) 有没有
unreleased_prefetch = Prefetch("chants", Chant.objects.with_audio())
teams = Team.objects.public().prefetch_related(unreleased_prefetch)
这很有效,但我还想知道这些对象的数量,并根据它们进行过滤。我很高兴目前可以使用queryset作为参数来预取对象(因为我大量使用自定义queryset/Manager)
有没有方法可以重复使用这个查询,我传递给预取对象的方式和条件注释相同
到目前为止,我的条件注释非常难看,看起来是这样的(它与我最初使用_audio自定义查询/筛选的chant的功能相同):
它是可行的,但相当丑陋,并且有重复的逻辑。
有没有办法将queryset传递到什么时候?我可以用同样的方法将它传递到预取以避免重复?并不是说这是最佳实践或其他方法,而是想提供一种处理这种情况的潜在方法
假设您有一个ChantQuerySet
类:
class ChantQuerySet(models.QuerySet):
def with_audio(self):
return self.filter(chants__has_audio_versions=True, chants__has_audio=True,
chants__flag_reject=False, chants__active=False)
作为一名管理者,您可能会使用它来执行以下操作:
class Chant(models.Model):
# ...
objects = ChantQuerySet.as_manager()
我建议将过滤器存储在QuerySet
中:
from django.db.models import Q
class ChantQuerySet(models.QuerySet):
@property
def with_audio_filter(self):
return Q(chants__has_audio_versions=True, chants__has_audio=True,
chants__flag_reject=False, chants__active=False)
def with_audio(self):
return self.filter(self.with_audio_filter)
这使您能够执行以下操作:
Chant.objects.annotate(
unreleased_count=Count(Case(
When(ChantQuerySet.with_audio_filter, then=1),
output_field=IntegerField()))
).filter(unreleased_count__gt=0)
现在,如果需要,您可以在一个地方更改过滤器,而无需在任何地方更改。对我来说,将这个过滤器存储在QuerySet
中是有意义的,就我个人而言,我看不出有什么问题,但那只是我自己
不过,我要改变的一件事是,在初始化ChantQuerySet
时,将with_audio\u filter
属性缓存,或者将其存储在构造函数中的一个字段中。这并不理想,但肯定至少解决了干式问题。谢谢你的建议!
Chant.objects.annotate(
unreleased_count=Count(Case(
When(ChantQuerySet.with_audio_filter, then=1),
output_field=IntegerField()))
).filter(unreleased_count__gt=0)