Django中的Forward Foreign Key与Reverse Foreign Key是什么?
Django中的正向外键(Forward Foreign Key)与反向外键(Reverse Foreign Key)定义
这两个是Django社区常用的非官方术语,官方文档里没有专门定义,但在讨论查询优化(比如select_related/prefetch_related)时经常被提到,结合你给出的模型代码,具体解释如下:
正向外键(Forward Foreign Key)
- 核心逻辑:在直接声明
ForeignKey字段的模型中,这个字段本身就代表正向外键关系。 - 对应你的模型:
Product模型里的category = models.ForeignKey(...)就是正向外键——Product主动关联到Category,从Product到Category的关联方向就是"正向"。 - 查询示例:拿到一个
Product实例后,直接通过product.category就能获取对应的分类对象。这类查询属于多对一关联,底层可以用SQL JOIN一次性拉取数据,所以适合用select_related优化N+1问题:
# 用select_related优化正向查询,避免重复查询数据库 products = Product.objects.select_related('category').all() for p in products: print(p.category.name) # 不会触发额外的SQL查询
反向外键(Reverse Foreign Key)
- 核心逻辑:从被
ForeignKey关联的目标模型,反过来关联到声明外键的模型的关系,Django会自动为这类模型生成反向关联属性。 - 对应你的模型:
Category没有直接声明外键,但Django自动生成了product_set属性(默认命名规则是[关联模型名小写]_set),通过它可以获取该分类下的所有Product实例,这就是反向外键关系。 - 查询示例:拿到一个
Category实例后,用category.product_set.all()获取所有关联产品。这类查询属于一对多反向关联,需要额外查询再拼接结果,所以适合用prefetch_related优化:
# 用prefetch_related优化反向查询,避免N+1问题 categories = Category.objects.prefetch_related('product_set').all() for c in categories: print([p.name for p in c.product_set.all()]) # 不会触发额外的SQL查询
- 自定义反向名称:你可以通过
ForeignKey的related_name参数修改默认的反向关联名称,比如把Product的外键改成:
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='products')
之后就可以用category.products.all()代替默认的product_set了。
内容的提问来源于stack exchange,提问作者Super Kai - Kazuya Ito
相关产品推荐
相关产品推荐

