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

maa*_*kle 5 python sql django django-models django-orm

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

考虑这个设置。我与自定义管理器建立了一对多关系,该管理器过滤掉书籍active=False

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()
Run Code Online (Sandbox Code Playgroud)

让我们创建一些数据:

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)
Run Code Online (Sandbox Code Playgroud)

从本质上讲,我永远不想处理不活跃的书籍。以下是一些用于测试各种场景的查询。

>>> 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.
Run Code Online (Sandbox Code Playgroud)

什么方法可以更改books__*查找的行为以包含附加过滤器active吗?

raf*_*lmp 1

引用文档

\n
\n

默认情况下,Django 在访问相关对象(即 choice.poll)时使用 \xe2\x80\x9cplain\xe2\x80\x9d 管理器类的实例,而不是相关对象上的默认管理器。这是因为 Django 需要能够检索相关对象,即使它会被默认管理器过滤掉(因此无法访问)。

\n

如果普通的普通管理器类(django.db.models.Manager)不适合您的情况,您可以通过在管理器类上设置 use_for_lated_fields 属性来强制 Django 使用相同的类作为模型的默认管理器。

\n
\n

所以你需要将你的经理更改为:

\n
class ActiveOnly(models.Manager):\n\n    use_for_related_fields = True\n\n    def get_queryset(self):\n        return super(ActiveOnly, self).get_queryset().filter(active=True)\n
Run Code Online (Sandbox Code Playgroud)\n