Django ForeignKey 外键详解:on_delete、related_name 与保存机制
本文深入解析 Django 模型中 ForeignKey 外键的核心用法。详细讲解 on_delete 参数的五种删除策略(CASCADE、PROTECT 等),说明 related_name 和 related_query_name 在反向查询中的区别与应用,并演示如何通过对象实例或 ID 保存外键字段,帮助开发者规范数据库关联设计。
本文档主要介绍 Django 框架中 Model 外键(ForeignKey)的处理机制及相关操作方法。
外键属于一对多字段类型,用于定义两张数据表之间的关联关系。
本文主要内容目录如下:
- on_delete 参数
- related_name 属性
- related_query_name 属性
- 外键字段的保存方式
1、on_delete 参数详解
假设存在两个 Django 应用,分别命名为 app1 和 app2。
在 app1 中定义一个名为 App1 的 Model。
在 app2 中定义一个名为 App2 的 Model。
# app1/models.py
class App1(models.Model):
app2 = models.ForeignKey("app2.App2", on_delete=models.CASCADE)
# app2/models.py
class App2(models.Model):
pass
在设置 ForeignKey 时,on_delete 参数用于指定当被关联的外键数据被删除时,当前 Model 数据的处理行为。
以上述两个 Model 为例,当 App2 中的某条数据被删除时,App1 中关联该数据的记录将依据 on_delete 策略进行处理。
常见的处理策略包括以下几种:
CASCADE(级联删除):当 App2 的数据被删除时,App1 中关联该数据的所有记录也将被同时删除。
PROTECT(保护模式):如果 App2 的数据被 App1 关联,则禁止删除该 App2 数据,会抛出 ProtectedError 异常。
SET_NULL(置空):当 App2 的数据被删除时,App1 中关联该数据的字段值将被设置为 NULL。注意,这要求该外键字段允许为 null。
DO_NOTHING(无操作):原数据不会有任何变更,即 App2 的某条数据被删除后,App1 中的引用依然保留。
需要注意的是,DO_NOTHING 通常不推荐在生产环境中使用。因为如果后续代码访问 App1 中该字段,尝试获取已删除的 App2 数据时,会引发数据库错误。
2、related_name 属性解析
ForeignKey 拥有一个名为 related_name 的属性,用于定义从相关对象反向访问当前对象的名称。该属性主要用于反向查询时的标识展示。如果未单独设置 related_query_name,则默认使用 related_name 的值。
特别注意:当同一个 Class 中存在两个或多个字段都指向另一个 Model 的外键时,必须为每个外键设置不同的 related_name,以区分不同的反向访问路径。
具体示例如下:
class Entry(models.Model):
blog_old = models.ForeignKey(Blog, related_name='old_entry')
blog_new = models.ForeignKey(Blog, related_name='new_entry')
3、related_query_name 属性解析
该字段主要用于反向过滤器(reverse filter)的搜索命名。若未单独赋值,系统将默认使用 related_name 的值。
为了说明反向过滤器的功能,参考以下两个 Model 的定义:
class Blog(models.Model):
pass
class Entry(models.Model):
blog = models.ForeignKey(Blog)假设现在数据库中已存在一条 Blog 数据。
blog_1 = Blog.objects.get(id=1)
若希望获取 Entry 表中 blog 字段值为 blog_1 的所有记录,常规做法如下:
entry_list = Entry.objects.filter(blog=blog_1)
由于 blog 字段是外键,我们可以利用 Django 提供的反向过滤器功能来实现:
entry_list = blog_1.entry_set.all()
上述即为反向过滤器的基本用法,即使用关联 Model 名称的小写形式加上 '_set' 后缀来操作,这是 Django 的默认固定用法。
如果在定义外键时设置了 related_query_name 字段,则可以废弃 'model_name_set' 的默认用法,直接通过设置的 related_query_name 进行反向查询。例如 Entry 定义如下:
class Entry(models.Model):
blog = models.ForeignKey(Blog, related_name="entries")
此时,若未单独设置 related_query_name 的值,系统将自动使用 related_name 的值。使用反向过滤器的方法如下:
entry_list = blog_1.entries.all()
4、外键字段的保存机制
首先介绍外键字段在 Django Model 定义与底层数据库结构中的表现形式。
在 Model 代码中,以 Entry 为例,关键的外键字段通常直接命名为 'blog'。
但在实际的数据库结构中,查看表结构时会发现该字段名为 'blog_id',即字段名加上 '_id' 后缀。
假设获取了一个 Entry 实例,变量名为 entry_obj。
entry_obj = Entry.objects.get(id=1)
当输出 entry_obj.blog 时,返回的是一个 Blog 的实例对象(object)。
而当输出 entry_obj.blog_id 时,返回的是一个整型(int)的主键 ID 值。
那么,如何为 Entry 实例保存 blog 字段呢?如果已有一个 Blog 实例 blog_1,可以直接赋值:
entry_obj.blog = blod_1
entry_obj.save()
如果已知某个 Blog 的主键 ID 为 blog_id,也可以通过 ID 进行赋值:
entry_obj.blog_id = blod_id
entry_obj.save()
至此,关于 Django 中 ForeignKey 外键的介绍与使用已讲解完毕。如需了解更多 Django 外键相关内容,建议查阅本站过往文章或继续浏览后续教程,感谢支持!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













