目录
Django 中基表的设置
断关联表关系
Django ORM 中外键字段属性详解
数据库中脏数据介绍
Django 中基表的设置
通过图书管理系统引入多表操作: 如果我们创建表的方式是先抽象出表与表之间相同的字段建一个父类, 然后在用每个表类去继承这个父类, 如下面的代码, 我们将无法得到期望的表字段.
- class BaseModel(models.Model):
- created_time = models.BooleanField(auto_now_add=True)
- id_delete = models.BooleanField(default=False)
- class Book(BaseModel):
- pass
- class Publisher(BaseModel):
- pass
通过这种继承方式无法完成表的继承, 如果要实现表的继承, 需要进行专门的设置将 Meta 的 abstract 设置为 True 下面这种写法就可以:
- class BaseModel(models.Model):
- is_delete = models.BooleanField(default=False)
- created_time = models.DateTimeField(auto_now_add=True)
- class Meta:
- abstract = True
- class Book(BaseModel):
- pass
- class Publisher(BaseModel):
- pass
Meta 类是 Django 的内嵌类, 它的作用是给自己的上级类添加一些功能或者指定一些标准, abstract = True 将该基类定义为抽象类, 即不生成数据库表单, 只作为一个可以继承的基类, 把一些子类必须的代码放在基类, 避免重复代码也避免重复录入数据库. db_table = 'axf_wheel'指定该类的数据库表单名字. 当然如果不指定也没关系, Django 会自动默认的按照一定规则生成数据模型对应的数据库表名. 关于 Django Meta 的详细讲解可以参考该博客.
断关联表关系
断关联表关系不会影响连表查询操作, 可以提升增删改效率, 易于后期数据库表的重构, 缺点: 数据库没有连表检测, 容易出现脏数据, 需要通过严格的逻辑避免脏数据的产生.
举例: 表 A 依赖表 B, 先插入表 A 的记录, 该记录对应的表 B 记的录没产生, 在没有关联的情况下, 该操作可以实现, 但是表 A 的数据就是脏数据. 接着再将表 B 对应的数据添加, 脏数据就得到处理了. 反过来先操作表 B 后操作表 A, 更满足逻辑思维, 一样可以执行. 通过逻辑将 A,B 表进行连表查询, 不会有任何异常. 如两张表建立了一对一外键字段, 外键在 A 表, 那么先往 B 表写数据就更合理.
假设图书管理系统中书, 出版社, 作者, 作者详细信息四张表之间的关系如下:
"""
表关系
1)Book 和 Publish 一对多: 外键在多的一方 Book
2)Book 和 Author 多对多: 外键在查询频率高的一方 Book
3)Author 和 AuthorDetail 一对一: 外键要根据实际需求建立在合理的位置 AuthorDetail(外键在 AuthorDetail 方作者就可以没有 AuthorDetail, 更合理)
"""
Django ORM 中外键字段属性详解
在建表之前我们对外键字段属性进行了解:
1)related_name 在外键中设置外键反向查询的字段名: 正向找字段名, 反向找 related_name 值, related_name 的默认值是表名小写 + _set, 这就是为什么在 Django 中跨表反向查询时我们使用表名小写 + _set 去查另一张表的数据.
2)on_delete 在外建中必须设置, 表示级联关系, 在 Django1.x 下系统默认提供 (值为 models.CASCADE),Django2.x 下必须手动明确:
CASCADE: 默认值, 级联
例子: 作者被删, 作者详情一定没有
DO_NOTHING: 外键不会被级联, 假设 A 表依赖 B 表, B 记录删除, A 表的外键字段不做任何处理
例子: 作者被删了, 作者的书还存在, 书还是该作者写的; 出版社没了, 出版社出版的书还在
SET_DEFAULT: 假设 A 表依赖 B 表, B 记录删除, A 表的外键字段重置为 default 属性设置的值, 所以必须配合 default 属性使用.
例子: 部门没有了, 部门员工里的部门字段改为未分组部门的 id
SET_NULL 使用的时候需要 NULL=True; 假设 A 表依赖 B 表, B 记录删除, A 表的外键字段重置为 NULL, 所以必须配合 NULL=True 使用.
例子: 部门没有了, 部门员工里的部门字段改为未分组部门的 id 字段为 NULL
注: 多对多字段不能设置 on_delete 级联关系, 如果要处理级联关系, 需要手动明确关系, 处理表关系中的多个外键
3)db_constraint 在外建中控制表关联, 默认为 True, 设置为 False 则断开关联, 断不断关联不会影响操作只会影响效率
- from django.contrib.auth.models import User
- class BaseModel(models.Model):
- is_delete = models.BooleanField(default=False)
- created_time = models.DateTimeField(auto_now_add=True)
- class Meta:
- # 基表, 为抽象表, 是专门用来被继承, 提供公有字段的, 自身不会完成数据库迁移
- abstract = True
- 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)
- #断开出版社与 book 之间的表关联, 取消两表的级联, 将默认值设置为空, 外键反向查询的字段名设置为 book
- authors = models.ManyToManyField(to='Author', related_name='books', db_constraint=False)
- def __str__(self):
- return self.name
- class Publish(BaseModel):
- name = models.CharField(max_length=64)
- address = models.CharField(max_length=64)
- class Author(BaseModel):
- name = models.CharField(max_length=64)
- class AuthorDetail(BaseModel):
- mobile = models.CharField(max_length=64)
- author = models.OneToOneField(to=Author, related_name='detail', db_constraint=False, on_delete=models.CASCADE)
- #断开 Author,AuthorDetial 表与表的关联, 将两张表设置为级联, 并将外键反向查询的字段名设置为 detail
数据库中脏数据介绍
数据库中常见的并发操作所带来了一致性问题包括: 丢失的修改, 不可重复读, 读 "脏" 数据, 幻读.
1. 丢失的修改: 一个事物的更新覆盖了另一个事物的更新. 例如: 事物 A 和 B 读入同一数据并修改, B 提交的结果破坏了 A 提交的结果, 导致 A 的修改被丢失.
2. 不可重复读: 一个事物两次读取同一个数据, 两次读取的数据不一致. 不可重复读是指事物 A 读取数据后, 事物 B 执行更新操作, 事务 A 无法再现前一次读取结果.
a. 事物 A 读取某一数据后, 事物 B 对其作了修改, 当事物 A 再次读取数据时, 得到与前一次不同的值.
b. 事物 A 按一定的条件从数据库中读取了某些数据后, 事物 B 删除了其中部分记录, 当 A 再次以相同条件读取时, 发现某些记录消失了.
3. 脏读: 一个事物读取了另一个事物未提交的数据. 读 "脏" 数据是指事物 A 修改某一数据, 并将其写回磁盘, 事物 B 读取同一数据后, A 由于某种原因被撤销, 这时 A 已修改过的数据恢复原值, B 读到的数据就与数据库中的数据不一致, 则 B 读到的数据为 "脏" 数据, 即不正确的数据.
4. 幻读: 一个事务按相同的查询条件重新读取以前检索过的数据, 却发现其他事务插入了满足其查询条件的新数据, 这种现象就称为 "幻读".
a. 事物 A 按一定的条件从数据库中读取某些数据记录后, 事物 B 插入了一些记录, 当 B 再次按照相同条件读取数据时, 发现多了一些记录.(也叫做幻影读).
产生上述三类数据不一致性的主要原因是并发操作破坏了事物的隔离性, 并发控制就是要用正确的方式调度并发操作, 使一个事物的执行不受其他事物的干扰, 从而避免造成数据的不一致性.
来源: http://www.bubuko.com/infodetail-3351849.html