赞
踩
# app/models.py
class App1(models.Model):
pass
class App2(models.Model):
app2 = models.ForeignKey(App1, on_delete=models.CASCADE)
假设有两个 application,app1
和 app2
app1
下的 某个 model 为 App1
app2
下的 某个 model 为 App2
# 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)
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')
示例如下:
# 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 来操作,这是一个固定用法。即 App2
是App1
的外键关联模型表
但是如果我们设置了 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()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。