ForeignKey 字段的定义如下:
`class ForeignKey(othermodel, on_delete, **options)’
第一个参数是关联的对象,第二个on_delete指示删除时的动作。
on_delete 参数值
- CASCADE: 级联删除
- PROTECT: 阻止删除并提示 ProtectedError
- SET_NULL: 设置为NULL值
- SET_DEFAUL: 设置默认值
SET(): 将传入SET方法的值作为值,传入的可以是一个函数:
1
2
3
4
5
6
7
8
9
10
11
12from 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),
)DO_NOTHING: 无动作。
如果不写,默认是CASCADE
limit_choice_to
对choice进行过滤,可以是字典也可以是一个Q查询组件,或者一个函数:1
2
3
4
5staff_member = models.ForeignKey(
User,
on_delete=models.CASCADE,
limit_choices_to={'is_staff': True},
)
函数:1
2
3
4def limit_pub_date_choices():
return {'pub_date__lte': datetime.date.utcnow()}
limit_choices_to = limit_pub_date_choices
related_name 和 related_query_name
当你的model中有两个或多个字段ForeignKey到同一个model,那么related_name必填。1
2
3
4class Meal(models.Model):
name = models.CharField('Name',max_length=10)
fruit = models.ForeignKey('Fruit')
fruit2 = models.ForeignKey('Fruit')
生成migrations的时候就会报:1
2
3
4
5ERRORS:
person.Meal.fruit2: (fields.E304) Reverse accessor for 'Meal.fruit2' clashes with reverse accessor for 'Meal.fruit'.
HINT: Add or change a related_name argument to the definition for 'Meal.fruit2' or 'Meal.fruit'.
person.Meal.fruit: (fields.E304) Reverse accessor for 'Meal.fruit' clashes with reverse accessor for 'Meal.fruit2'.
HINT: Add or change a related_name argument to the definition for 'Meal.fruit' or 'Meal.fruit2'.
的错误,因为不指明related_name,django区别不了这两个字段。所以,我们加上related_name:1
2
3
4class Meal(models.Model):
name = models.CharField('Name',max_length=10)
fruit = models.ForeignKey('Fruit',related_name='frist_meal')
fruit2 = models.ForeignKey('Fruit',related_name="second_meal")
数据库中,django自动为我们这两个字段起的名字是字段名+_id的形式,这里分别是fruit_id和fruit2_id,如果想自定义这个字段名,使用参数db_column。
related_query_name 默认值同 related_name,用于外键对象反查本对象。例如,我们可以通过如下的方式查询Meal:1
2
3
4
5
6
7
8from person.models import Fruit,Meal
apple = Fruit.objects.create(name="apple")
banana = Fruit.objects.create(name="banana")
m = Meal.objects.create(name="Big Meal",fruit=apple,fruit2=banana)
Fruit.objects.get(MoringFruit=m).name #apple
Fruit.objects.get(AfternoonFruit=m).name #banana
一般情况下,relate_name和related_query_name保持一致即可。但是在继承中一需要保证抽象父类和子类的名称不一致。
1 | class Meal(models.Model): |
其中app_label是app的名字,class是类名,最后组合出来的名称均用小写。例如:person_breakfast_first_meal=br
有时候会遇见related_name=+或者以+号结尾,意思是禁止反查。
to_field
外键对象的关联字段,默认为id,如果指定了别的字段,该字段必须设置unique=True.
db_constraint
指定是否添加数据库限制,默认为True,一般不需要设置为False
swappable
保持默认即可,如果想知道什么是swappable models,看这里