基表
基表,是抽i想表,数据迁移的时候不会创建基表,仅作为models文件中为其他表服务的虚拟基表.
设置基表
需要在基表中配置类中加abstract=True
class BaseModel(models.Model):
is_delete = models.BooleanField(default=False)
created_time = models.DateTimeField(auto_now_add=True)
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
<span class="hljs-comment"># 基表,为抽象表,是专门用来被继承,提供公有字段的,自身不会完成数据库迁移</span>
abstract = <span class="hljs-keyword">True</span></code></pre>
外键字段属性
前提,db_constraint为true
on_delete属性
django1中默认on_delete是model.CASCADE级联删除
设置级联删除的数据在数据库中无法手动删除,但是可以通过orm语句删除.
设定了当被关联表被删除时,主表此外键相对应数据如何变化
设:A为主表,B为被关联表
on_delete:model.CASCADE
默认值,级联删除
一旦外键设置db_constraint,级联失效
on_delete:model.DO_MOTHING
外键不会被级联
敌不动我不动,敌动我害不动
on_delete:model.SET_DEFAULT
删除B记录,A中外键字段被设置为default,必须配合default属性使用
on_delete:model.SET_NULL
删除B记录,A中外键字段被设置null,必须配合null=True属性使用
on_delete:model.PROTECT
保护模式,使用该选项,删除的时候,会抛ProtectedError错误
on_delete:model.SET()
自定义一个值,该值当然只能是对应的实例了
**官方案例**
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),
)
注意:
on_delete属性只能设置在外键字段中(ForeignKey,或者OneToOneField,OneToOneField继承了ForeignKey),因为全自动ManyToManyField是通过第三章表实现,所以两表并无直接联系,可以通过半自动或手动设置关联.
related_name属性
设置反向查询(即从被关联表查询主表),返回queryset对象
publish = Publish.objects.filter(pk=1).first()
books = publish.books.all().first() #type:Book
print(books.name,2)
print(type(books))
>>>
西游记 2
<class 'api.models.Book'>
设置related_name后依旧可以使用原生反向跨表查询,但是注意这个时候原表的字段已经改名为related_name="xxx"中的xxx
book = Publish.objects.filter(books__pk=1).first() #注意这里要使用books进行反向查询,原表名小写book已经无效.
print(book.name,'1')
>>>
北京 1
db_constraint属性
在外键中控制两关联表之间的联系,默认值为True表示关联,设置False表示断开关联.
class Book(BaseModel):
name = models.CharField(max_length=64)
price = models.DecimalField(max_digits=10, decimal_places=2)
publish = models.ForeignKey(to='Publish', related_name='books', db_constraint=False, on_delete=models.DO_NOTHING, null=True)
authors = models.ManyToManyField(to='Author', related_name='books', db_constraint=False)
深度查询
外键字段默认显示的是外键值(int类型),不会自动进行深度查询
深度查询方法:
- 子序列化:必须有子序列化类配合,不能反序列化
- 配置depth:自动进行关联表所有字段的深度查询,数据无法自定义
- 插拔式@propety:名字不能与外键名同名