如何在链查询中使用自定义管理器?

I15*_*159 13 django django-queryset django-managers

我做了一个自定义管理器,必须随机化我的查询:

class RandomManager(models.Manager):

    def randomize(self):        
        count = self.aggregate(count=Count('id'))['count']
        random_index = random.randint(0, count - 1)
        return self.all()[random_index]
Run Code Online (Sandbox Code Playgroud)

当我首先使用我的经理中定义的方法时,它可以正常工作:

>>> PostPages.random_objects.randomize()
>>> <PostPages: post 3>
Run Code Online (Sandbox Code Playgroud)

我需要随机化已经过滤的查询.当我尝试使用管理器和链中的方法时出现错误:

PostPages.random_objects.filter(image_gallary__isnull=False).randomize()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/home/i159/workspace/shivaroot/shivablog/<ipython-input-9-98f654c77896> in <module>()
----> 1 PostPages.random_objects.filter(image_gallary__isnull=False).randomize()

AttributeError: 'QuerySet' object has no attribute 'randomize'
Run Code Online (Sandbox Code Playgroud)

过滤的结果不是模型类的实例,但它是django.db.models.query.QuerySet,因此它分别没有我的经理和方法. 有没有办法在链查询中使用自定义管理器?

zza*_*art 27

这就是你如何在自定义管理器上链接自定义方法,即:Post.objects.by_author(user = request.user).published()

from django.db.models.query import QuerySet

class PostMixin(object):
    def by_author(self, user):
        return self.filter(user=user)

    def published(self):
        return self.filter(published__lte=datetime.now())

class PostQuerySet(QuerySet, PostMixin):
    pass

class PostManager(models.Manager, PostMixin):
    def get_query_set(self):
        return PostQuerySet(self.model, using=self._db)
Run Code Online (Sandbox Code Playgroud)

链接到这里:django-custom-model-manager-chaining

注意 :

在Django 1.7中你可以开箱即用.查看QuerySet.as_manager

  • 为Django 1.7做+1的方法,但不应该是QuerySet.as_manager()?在我看来,这也应该标记为正确答案. (3认同)

ari*_*rie 12

看起来这个代码段为您的情况提供了解决方案:具有可链接过滤器的自定义管理器.

  • 如果你正在使用Django 1.7+,请参阅下面的答案,因为功能开箱即用. (4认同)

Zhe*_* Li 10

只是使用新的as_manager()方法的代码示例(请参阅@zzart的更新信息.

class MyQuerySet(models.query.QuerySet):
    def randomize(self):        
        count = self.aggregate(count=Count('id'))['count']
        random_index = random.randint(0, count - 1)
        return self.all()[random_index]

class MyModel(models.Model):
    .....
    .....
    objects = MyQuerySet.as_manager()
    .....
    .....
Run Code Online (Sandbox Code Playgroud)

然后你就可以在你的代码中使用这样的东西了:

MyModel.objects.filter(age__gt=16).randomize()
Run Code Online (Sandbox Code Playgroud)

如你所见,新的as_manager()非常整洁:)

  • 刚刚使用`.as_manager()`并验证了这是实现它的方法.谢谢. (2认同)