Django - 关于 models.py 模型的外键方法使用总结 - 1

一、如何构建模型外键

1. app内的外键构建

# app/models.py

class App1(models.Model):
	pass

class App2(models.Model):
    app2 = models.ForeignKey(App1, on_delete=models.CASCADE)
    

2. 跨app的外键构建

假设有两个 applicationapp1app2

app1 下的 某个 modelApp1

app2 下的 某个 modelApp2

# app1/models.py
class App1(models.Model):
	pass

构建app1应用的App1表的外键,其中app2应用模型文件内的App2表是App1表的外表。

# app2/models.py
class App2(models.Model):
      app1 = models.ForeignKey("app1.App1", on_delete=models.CASCADE)

二、外键约束 - 删除操作的参数配置

CASCADE级联更新操作。如果外键对应的那条数据被删除了,那么这条数据也会被删除。 (最常用的配置

# app/models.py
app2 = models.ForeignKey(App1, on_delete=models.CASCADE)

PROTECT受保护。即只要这条数据引用了外键的那条数据,那么就不能删除外键的那条数据。
如果我们强行删除,Django就会报错。

# app/models.py
app2 = models.ForeignKey(App1, on_delete=models.PROTECT)

SET_NULL设置为空。如果外键的那条数据被删除了,那么在本条数据上就将这个字段设置为空。
如果设置这个选项,前提是要指定这个字段可以为空。blank=True, null=True 可以指定字段为空字段,不过Django通常都会给数据库表空字段配置空字符串 ' ',把null改为 ' '

# app/models.py
app2 = models.ForeignKey(App1, on_delete=models.SET_NULL, blank=True, null=True)

详解Django 中的blank=True 和 null=True

SET_DEFAULT设置默认值。如果外键的那条数据被删除了,那么本条数据上就将这个字段设置为默认值。
如果设置这个选项,前提是要指定这个字段一个默认值

# app/models.py
app2 = models.ForeignKey(App1, default='test_default', on_delete=models.SET_DEFAULT)

SET(value):如果外键的那条数据被删除了。那么将会获取SET函数中的值(value)来作为这个外键的值。SET函数可以接收一个可以调用的对象(比如函数或者方法)。
如果是可以调用的对象,那么会将这个对象调用后的结果作为返回值return返回回去。可以不用指定默认值

# app/models.py
app2 = models.ForeignKey(App1, default='test_set', on_delete=models.SET(value))

DO_NOTHING:不采取任何行为。一切全看数据库级别的约束。

DO_NOTHING,不处理,原数据不会有任何操作,也就是说 App1 的某条数据被删除,App2 中的引用还在,其实就是外表的外键还在。 但其实这是一种不推荐的做法,因为如果访问到App2 中的这条数据,用到了 app1 这个字段,就会报错,因为有一条数据被删除了,那么外键表内就有一条数据的外键和主表的外键对应不上,找不到,就报错了。

# app/models.py
app2 = models.ForeignKey(App1, default='test_nothing', on_delete=models.DO_NOTHING)

三、多表外键绑定,起别名 - related_name

ForeignKey 有一个属性,related_name,用于表示从相关对象到此对象的关系的名称,仅用于展示,但是如果related_query_name 字段没有被赋值的话,那么 related_query_name 则会默认使用related_name 这个值。(不清楚是真有releted_query_name,原文不知道是不是写错了,感觉有点矛盾,我就先自己琢磨理解为自己的东西)

也就是说会默认使用下面那个例子的 App2_old 和 App2_new 作为字段名。

注意: related_name 还有一个用途,就是在同一个 class 下面,指模型表,如果有两个创建的外键字段都是相同 model 的外键字段,这时候添加 related_name 用来区分两个字段是必须的。

示例如下:

# app/models.py
class App2(models.Model):
    App1_old = models.ForeignKey(App1, related_name='old_app1')
    App1_new = models.ForeignKey(App1, related_name='new_app1')
    

1. 别名的实际应用 - 外键值查询 - 反向过滤器的搜索

示例如下:

# app/models.py
class App1(models.Model):
	# 正常字段
	app1_data= models.CharField(verbose_name='信息', max_length=255) 

 
class App2(models.Model):
    app1= models.ForeignKey(App1)  # 外键字段

现在我们获取了 App1 表的一个数据,变量名为 app1_1,值为xxx

app1_1 = App1.objects.get(id=1) # 获取App1表 id 为 1 的一行数据

如果我们想要获取 App1 表里所有 app1_data 这个字段的值为 app1_1,怎么处理呢?一般来说是:

# 获取只要是app1_data字段内的值满足app1_1,即等于app1_1的值,
# 就作为返回数据之一,返回值类型 列表
app1_list = app1.objects.filter(app1_data=app1_1) 

正常情况下,获取某张表内的的信息是按上面的方法搜索的,即SQL语句是这样子的 SELECT * FROM App1 WHERE app1_data='xxx';

但是如果是要获取主表的所有外键字段的数据,就需要使用下面的方法来获取。

app1_list = app1_1.app2_set.all()

上面就是我们 反向过滤器 的用法,就是使用外键关联的model 的名称的小写形式 + _set 来操作,这是一个固定用法。即 App2App1的外键关联模型表

但是如果我们设置了 related_name 这个属性, model名称小写+’_set’ 的用法就可以废弃了,可以直接使用 related_name 来操作,比如 App2如下,

示例演示:

# app/models.py
class App2(models.Model):
    App1_fork = models.ForeignKey(App1, related_name='app1_fork')
    

获取App1表的所有外键:(注意是查外键是主表App1的数据调用反向过滤器,而不是外键表App2的数据是主表的)

app1_fork_list = app1_1.app1_fork.all()

参考链接

Django中外键ForeignKey介绍使用

Django中外键使用详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值