python – Django覆盖查询中双下划线关系查找的行为

我的主要问题是:有没有办法改变相关查找的行为,例如MyModel.objects.filter(relationship__field =“value”)?

考虑这个设置.我与自定义管理器建立了一对多的关系,该管理器使用active = False过滤掉Books

from django.db import models


class ActiveOnly(models.Manager):

    use_for_related_fields = True

    def get_queryset(self):
        return super(ActiveOnly, self).get_queryset().filter(active=True)

class Author(models.Model):
    name = models.TextField()

class Book(models.Model):
    active = models.BooleanField()
    author = models.ForeignKey(Author, related_name="books")
    title = models.TextField()
    objects = ActiveOnly()

让我们创建一些数据:

jim = Author.objects.create(name="Jim")
ulysses = Book.objects.create(title="Ulysses", author=jim, active=True)
finnegans = Book.objects.create(title="Finnegan's Wake", author=jim, active=False)

bill = Author.objects.create(name="Bill")
hamlet = Book.objects.create(title="Hamlet", author=bill, active=False)

从本质上讲,我从不想要处理非活动的书籍.以下是一些测试各种场景的查询.

>>> Book.objects.all().count()  # expecting the 1 active book: good
1  
>>> jim.books.all()  # also expecting only 1: good
1
>>> Author.objects.filter(books__title="Hamlet").first().name
u'Bill'  
# ^ this is what I don't want to see, because bill's only book has active=False.
# I want the queryset to return no results.

有没有办法改变书籍的行为__ *查找以包含活动的附加过滤器?

最佳答案 引用
documentation

By default, Django uses an instance of a “plain” manager class when accessing related objects (i.e. choice.poll), not the default manager on the related object. This is because Django needs to be able to retrieve the related object, even if it would otherwise be filtered out (and hence be inaccessible) by the default manager.

If the normal plain manager class (django.db.models.Manager) is not appropriate for your circumstances, you can force Django to use the same class as the default manager for your model by setting the use_for_related_fields attribute on the manager class.

所以你需要将经理改为:

class ActiveOnly(models.Manager):

    use_for_related_fields = True

    def get_queryset(self):
        return super(ActiveOnly, self).get_queryset().filter(active=True)
点赞