Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django自定义预取和条件注释_Django_Django Queryset - Fatal编程技术网

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)