在 Django 模型的关联字段(如 ForeignKey ManyToManyField 等)中, related_name 和 related_query_name 都是用于优化反向操作的参数,但它们的作用场景和对象完全不同。
核心区别
| 参数 | 作用场景 | 操作对象 | 简单说就是... |
|---|---|---|---|
| related_name |
反向获取关联对象 (属性访问) |
模型实例 (如author.books) |
实例用: 通过被关联模型实例查关联数据 |
| related_query_name | 反向过滤查询(filter/exclude 等) |
QuerySet Author.objects.filter(books__title...) |
查询用:在过滤条件中引用关联关系 |
详细说明与示例
假设我们有两个模型:Author(作者)和 Book(书籍),通过 ForeignKey 关联:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(
Author,
on_delete=models.CASCADE,
related_name="books", # 自定义反向关联名称
related_query_name="book" # 自定义反向查询名称
)
1. related_name:反向获取关联对象(实例属性)
related_name 定义了从被关联模型实例出发,获取关联模型实例的属性名。例如,从 Author 实例(被关联模型)查询其关联的 Book 实例(关联模型):
# 获取 ID=1 的作者
author = Author.objects.get(id=1)
# 通过 related_name "books" 获取该作者的所有书籍(实例属性访问)
books = author.books.all() # 返回 QuerySet:[<Book: Django入门>, <Book: Python进阶>]
- 如果不指定
related_name,默认值为[关联模型小写类名]_set(如book_set),即author.book_set.all()。
2. related_query_name:反向过滤查询(QuerySet 条件)
related_query_name 定义了在被关联模型的 QuerySet 过滤条件中,引用关联模型的名称。例如,在 Author.objects.filter(...) 中,通过关联的 Book 字段过滤作者:
# 查找所有写过标题包含 "Django" 的书籍的作者
# 这里的 "book" 就是 related_query_name
authors = Author.objects.filter(book__title__contains="Django")
- 过滤条件中的
book__title表示:通过related_query_name为book的关联关系,过滤title字段。 - 如果不指定
related_query_name,默认值为related_name的值(若related_name也未指定,则默认是[关联模型小写类名])。
对比:当两者值不同时
如果将 related_name 和 related_query_name 设为不同的值,区别会更明显:
class Book(models.Model):
author = models.ForeignKey(
Author,
on_delete=models.CASCADE,
related_name="written_books", # 实例访问用
related_query_name="written_book" # 查询过滤用
)
- 实例访问(
related_name):author.written_books.all()# 获取该作者写的所有书 - 查询过滤(
related_query_name):Author.objects.filter(written_book__title__contains="Python")# 过滤写过 Python 书籍的作者
总结
related_name:给模型实例用,定义 “从被关联模型实例出发,如何称呼关联模型的集合”(如author.books)。related_query_name:给QuerySet 查询用,定义 “在过滤条件中,如何引用关联模型”(如filter(book__title...))。
实际开发中,若两者无需区分,可只指定 related_name(此时 related_query_name 会默认沿用其值);若需更清晰的语义(如实例用复数、查询用单数),可分别指定。