参考资料以下html
ForeignKey
用于多对一关系,直接对应到数据库外键的概念。使用ForeignKey
须要指定引用的目标表,会自动关联到目标表的主键(通常是id
字段)。python
例子以下。sql
from django.db import models class Child(models.Model): parent = models.ForeignKey('Parent', on_delete=models.CASCADE, ) # ... class Parent(models.Model): # ... pass
对比之 sqlalchemy,一行parent=models.ForeignKey(...)
包含了 sqlalchemy 中的ForeignKey
和relationship
两部份内容。数据库
on_delete
意为当ForeignKey
引用的对象被删除时进行的操做。django
有几个能够考虑的选项。后端
CASCADE
意为级联,on_delete
设置为CASCADE
时意为执行级联删除。依据文档,Django 会模仿 SQL 的ON DELETE CASCADE
,对包含了ForeignKey
的对象执行删除。app
须要注意的是不会调用被级联删除对象上的model.delete()
,可是会发送pre_delete
和post_delete
信号。post
PROTECT
意为保护,on_delete
设置为PROTECT
意味着要阻止删除操做发生。删除关联的对象时,ForeignKey
的on_delete
设置为PROTECT
会触发ProtectedError
。code
如其名所述,若是这个ForeignKey
是 nullable 的,则关联的对象删除时将外键设置为 null。orm
如其名所述,若是这个ForeignKey
设置了DEFAULT
,则关联的对象删除时设置这个外键为DEFAULT
值。
在关联的对象删除时,设置为一个指定的值。这个参数能够接受一个能够赋值给这个 ForeignKey 的对象或者一个可调用对象。
官方例子以下。
from django.conf import settings from django.contrib.auth import get_user_model from django.db import models def get_sentinel_user(): return get_user_model().objects.get_or_create(username='deleted')[0] class MyModel(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel_user), )
应该不用多说了吧。Django 不会作多余的事情,可是若是后端的数据库服务有强制完整性约束,除非你在数据库一端本身定义了ON DELETE
,不然会触发IntegrityError
。
强制约束为 django.admin 或者 ModelForm 渲染时提供有限的可选项。
接受参数为dict
或者Q
对象、返回Q
对象的可调用对象。
官方例子。
staff_member = models.ForeignKey( User, on_delete=models.CASCADE, limit_choices_to={'is_staff': True}, )
Q 对象是什么玩意儿这个我搞明白了再说...
设置反向关联的字段名,和sqlalchemy
的backref
相似。
举例来讲。
class Child(models.Model): parent = models.ForeignKey('Parent') class Parent(models.Model): pass Parent.child_set.all() # 未设置 related_name Parent.children.all() # 设置 related_name=children
related_query_name 和 related_name 相似,设置反向引用查询时条件的前缀名。举例来讲。
class Child(models.Model): parent = models.ForeignKey('Parent') name = models.CharField(max_length=4) class Parent(models.Model): pass Parent.objects.filter(Child__name='沙雕网友') # 未设置 related_query_name Parent.objects.filter(myboy__name='沙雕网友') # 设置 related_query_name=myboy
获得ForeignKey
关联的模型的字段,默认是主键,若是指定的不是主键那么必须有unique
约束才行。
要不要建立数据库层级的约束,也就是经过后端数据库服务确保数据完整性不受破坏。若是设置为 False 那么访问不存在的对象时会触发 DoesNotExists 异常。
用于处理“我有一个抽象类模型可是这个模型有一个外键”的状况,典型就是AUTH_USER_MODEL
。
通常不用改到,这个属性控制了数据库迁移时如何处理这个外键关联的表,总之保持默认值就好了。
这个功能支持了使用自定义的用户模型替代 django.auth.models.User
之类的玩意儿。
OneToOneField
基本就是一个加了unique
约束的ForeignKey
。使用上与 ForeignKey 略有不一样。
首先是访问 OneToOneField
时,获得的不是 QuerySet
而是一个对象实例。
# 优生优育政策( class Parent(models.Model): child = OneToOneField('Child') class Child(models.Model): pass parent.child # => 获得一个 Child 实例
其次是反向引用的名字是模型名字小写。
child.parent # => 获得一个 Parent 实例
若是指定 related_name
那就和 ForeignKey
一个表现。
基本和ForeignKey
相同。
ForeignKey
相同的参数limited_choices_to 在指定自定义中间表的状况下无效。
用于处理一个表本身对本身的多对多引用对称性。
Django 的默认行为是,我是你的朋友,那么你就是个人朋友。
设置了这个参数则强迫 Django 改变这个行为,容许“被朋友”。
默认状况下,Django 会自行建立中间表,这个参数强制指定中间表。
默认中间表模型里包含三个字段。
若是是本身和本身的多对多关系,则
当自行指定中间表,中间表又包含了多个外键时,指定关联的外键用。
举例。
class ModelA(models.Model): b = models.ManyToManyField(ModelB, through='ModelC') class ModelB(models.Model): pass class ModelC(models.Model): a=models.ForeignKey('ModelA') b=models.ForeignKey('ModelB') c=models.ForeignKey('ModelA')
此时在中间表中a
和c
都是对ModelA
的外键,产生了歧义,Django 没法自行决定用哪一个外键来关联 AB 两个表。
这时提供参数。
b = models.ManyToManyField('ModelB', through='ModelC', through_fields=(a, b))
ManyToManyField
关联两个表老是不对称的关系(指我把你当兄弟,你却想当我爸爸这样的关系。此时“我”对“你”的“兄弟”关系就是单向的。),这就造成了来源和目标的概念。
through_fields
的第一个元素总被认为是来源字段,第二个元素是目标字段。
指定 Django 建立的中间表的名字,默认根据两个表表名和 ManyToManyField
的名字决定。