在 Django 中,双下划线(__
)约定通常用于执行一些特定的查询操作,尤其是在使用 Django ORM 进行数据库查询时。这种约定被称为双下划线查询语法。
双下划线查询语法允许你在查询中使用类似于 SQL 的语法,以执行复杂的过滤、联结和聚合操作。下面是一些常见的用法:
-
字段查找:使用双下划线可以跨越关系进行字段查找,例如:
Entry.objects.filter(blog__name='example')
这将返回所有
Entry
对象,其关联的Blog
对象的名称是 ‘example’。 -
双下划线操作符:在查询中可以使用一些双下划线操作符,例如:
exact
:精确匹配。iexact
:忽略大小写的精确匹配。contains
:包含。icontains
:忽略大小写的包含。in
:在某个范围内。gt
:大于。lt
:小于。- 等等…
-
聚合操作:双下划线也可以用于执行聚合操作,例如:
from django.db.models import Count Author.objects.annotate(num_books=Count('book'))
这将为每个作者对象添加一个
num_books
属性,表示该作者拥有的书籍数量。 -
反向关系查询:双下划线可以在反向关系上使用,例如:
Blog.objects.filter(entry__headline__contains='Lennon')
这将返回所有博客,其关联的任何条目的标题包含 ‘Lennon’。
双下划线查询语法是 Django 中非常强大且常用的特性之一,它使得数据库查询变得灵活而强大,允许你以简单的方式执行复杂的查询。
详解
当你执行Entry.objects.filter(blog__name='example')
这样的查询时,你实际上是在查询名为Entry
的模型的对象,但是你想要过滤这些Entry
对象,以便它们关联的Blog
对象的名称为"example"。
让我们来详细解释这个查询:
-
Entry.objects.filter()
:这是一个查询集(QuerySet)方法,它允许你过滤模型的对象。Entry
是一个模型类,objects
是默认的管理器,filter()
用于过滤查询集。 -
blog__name='example'
:在这个过滤器中,blog
是Entry
模型中一个外键字段(或者是一个一对一字段),它将Entry
模型与Blog
模型相关联。name
是Blog
模型中的一个字段。blog__name
的含义是从Entry
模型跨越blog
关系,进而查找Blog
模型的name
字段。blog
是Entry
模型中的外键(或一对一)字段,它指向了相关联的Blog
对象。name
是Blog
模型中的一个字段,你想要对这个字段进行过滤。__
双下划线表示在模型之间进行关联查询。
因此,这个查询将返回所有Entry
对象,它们关联的Blog
对象的名称为"example"的条目。
以下是一个简单的示例模型代码,包含了两个模型:Entry
和Blog
。Entry
模型包含了一个外键字段指向Blog
模型。
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __str__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
def __str__(self):
return self.headline
在这个示例中,Entry
模型有一个名为blog
的外键字段,它关联到Blog
模型。这个外键字段表示了一个Entry
对象与一个Blog
对象的关系。每个Entry
对象都关联到一个Blog
对象,因此你可以通过Entry
对象的blog
属性访问关联的Blog
对象。
在进行查询时,你可以使用双下划线语法来跨越这种关系,例如:Entry.objects.filter(blog__name='example')
。