目录
一.如何开启事务
1.ACID是数据库事务的四个关键特性
- 它代表了原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)
- 原子性(Atomicity):
- 事务被视为一个不可分割的原子操作单元
- 这意味着要么全部操作成功并永久保存,要么全部失败并回滚到事务之前的状态,不存在部分成功或部分失败的情况
- 一致性(Consistency):
- 事务在执行前后,数据库必须保持一致状态
- 这意味着事务执行前后,数据库中的数据必须满足所有定义的完整性约束,例如列级别的约束,外键关系等
- 隔离性(Isolation):
- 事务之间应该相互隔离,每个事务的执行应该与其他事务的执行相互独立,互不干扰
- 隔离性确保了多个事务可以并发执行,而不会产生不一致的结果
- 持久性(Durability):
- 一旦事务成功提交后,其所做的修改将永久保存在数据库中,即使发生系统故障或重启,数据也能够恢复到提交后的状态
- 持久性通过将事务日志写入非易失性存储介质来实现,如硬盘驱动器或固态硬盘
- 原子性(Atomicity):
2.如何开启事务
from django.db import transaction
try:
with transaction.atomic():
# sql 1
# sql 2
# 在with代码块内书写所有的orm操作
# 这些操作都属于同一个事务
except Exception as e:
print(e)
print('执行其他操作')
二.常见的字段类型和参数
1.常见的关系字段
AutoField
# int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。
IntegerField
# 一个整数类型,范围在 -2147483648 to 2147483647。
CharField
# 字符类型,必须提供max_length参数, max_length表示字符长度。
DateField
# 日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。
DateTimeField
# 日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例
BigAutoField(AutoField)
# - bigint自增列,必须填入参数 primary_key=True
SmallIntegerField(IntegerField):
# - 小整数 -32768 ~ 32767
PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
# - 正小整数 0 ~ 32767
BigIntegerField(IntegerField):
# - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
BooleanField(Field)
# - 布尔值类型
True/False 1/0
name varchar(1024)
content text;
TextField(Field)
# - 文本类型
FileField(Field)
# - 字符串,路径保存在数据库,文件上传到指定目录
'''- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
'''
ImageField(FileField)
# - 字符串,路径保存在数据库,文件上传到指定目录
'''
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
'''
TimeField(DateTimeCheckMixin, Field)
# - 时间格式 HH:MM[:ss[.uuuuuu]]
FloatField(Field)
# - 浮点型
DecimalField(Field)
# - 10进制小数
'''
- 参数:
max_digits,小数总长度
decimal_places,小数位长度
'''
BinaryField(Field)
# - 二进制类型
2.ORM字段参数
null
# 用于表示某个字段可以为空。
**unique**
# 如果设置为unique=True 则该字段在此表中必须是唯一的 。
**db_index**
# 如果db_index=True 则代表着为此字段设置索引。
**default**
# 为该字段设置默认值。
DateField和DateTimeField
auto_now_add
# 配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
auto_now
# 配置上auto_now=True,每次更新数据记录的时候会更新该字段。
3.关系字段
ForeignKey
to
# 设置要关联的表
to_field
# 设置要关联的表的字段
related_name
# 反向操作时,使用的字段名,用于代替原反向查询时的’表名_set’。
on_delete
# 当删除关联表中的数据时,当前表与其关联的行的行为。
models.CASCADE
# 删除关联数据,与之关联也删除
models.DO_NOTHING
# 删除关联数据,引发错误IntegrityError
models.PROTECT
# 删除关联数据,引发错误ProtectedError
models.SET_NULL
# 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
models.SET_DEFAULT
# 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
models.SET
# 删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
db_constraint
# 是否在数据库中创建外键约束,默认为True。
OneToOneField(unique):ForeignKey(unqiue=True)
unique
4.choice参数
(1)引入
以一张信息表为例
性别
学历
工作经验
是否婚配
客户来源等
- 针对某个可以列举完全的可能性字段,我们应该如何存储?
- 只要某个字段的可能性是列举完全的,那么一般情况下都会采用choice参数
(2)数据准备
from random import choices
from django.db import models
# Create your models here.
class User(models.Model):
username = models.CharField(max_length=32)
age = models.IntegerField()
# 性别
gender_choices = (
(1, 'male'),
(2, 'female'),
(3, 'other'),
)
score = (
('1', 'male'),
('2', 'female'),
('3', 'other'),
)
# 保证字段类型跟列举出来的元祖第一个数据类型一致即可
gender = models.IntegerField(choices=gender_choices)
'''
该gender字段存的还是数字 但是如果存的数据在上面元祖列举的范围之内
那么可以非常轻松的获取到数字对应的真正内容
'''
1.gender字段存的数字不在上述元祖列举的范围内会如何?
2.如果数字在,如何获取对应的中文注释?
(3)问题解决
gender字段存的数字在上述元祖列举的范围内
from django.test import TestCase
# !/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day08.settings")
import django
django.setup()
from app01 import models
models.User.objects.create(username="dream", age=18, gender=1)
models.User.objects.create(username="mengmeng", age=28, gender=2)
models.User.objects.create(username="chimeng", age=39, gender=3)
# 存的时候,没有列举出来的数字也能被存进去
models.User.objects.create(username="hope", age=44, gender=4)
没有报错且第四条已经插入到数据库中
gender字段存的数字在上述元祖列举的范围内并获取
# 取 - 如果有对应关系
user_obj = models.User.objects.filter(pk=1).first()
print(user_obj.gender) # 1
# 只要是 choice字段的注释,如果想要获取到注释的信息,固定写法 get_字段名_display()
print(user_obj.get_gender_display()) # male
gender字段存的数字不再上述元祖列举的范围内
# 取 - 如果没有对应关系
user_obj = models.User.objects.filter(pk=4).first()
# 如果没有对应关系 字段是什么 返回的就是什么
print(user_obj.get_gender_display()) # 4
(4)总结
- choice参数使用的场景非常广泛
- 支付方式的选择
- 生源的来源地
- 分数的分类
- 学历的分类等
三.MTV和MVC模型
MTV模型和MVC模型是两种常见的软件设计模式,用于组织和管理用户界面和应用程序的逻辑
1.MTV模型
MTV模型是指Model-Template-View(模型-模板-视图)模型。是Django框架中采用的一种设计模式,它的核心思想是将应用程序分为三个主要部分:模型、模板、视图
- 模型:
- 模型表示应用程序中处理数据的结构和行为
- 它通常与数据库交互,并定义了数据的存储和操作方式
- 模板:
- 模板负责处理用户界面的显示
- 它定义了应用程序的外观和布局,并将动态数据与静态页面结合在一起,生成最终的用户界面
- 视图:
- 视图处理应用程序的逻辑和业务流程
- 它接收用户的请求,从模型中获取数据,将数据传递给模板进行渲染,并生成响应返回给用户
MTV模型的优点在于它可以很好地将应用程序的逻辑和用户界面进行分离,使代码更容易维护和扩展
2.MVC模型
MVC模型是指Model-View-Controller(模型-视图-控制器)模型,是一种常见的软件设计模式,广泛应用于Web开发和其他应用程序中
- 模型:
- 模型负责处理应用程序的数据逻辑
- 它包含了数据的存储和操作方式,并定义了数据在应用程序内部如何交互和操作
- 视图
- 视图是用户界面的显示,负责展示数据给用户并接收用户的输入操作
- 它通常从模型中获取数据,并将其显示给用户
- 控制器
- 控制器处理用户的交互和请求,并根据用户的行为做出相应的响应
- 它接收用户的输入,并更新模型和视图以反映给用户的操作
MVC模型的优点在于它可以很好的分离应用程序不同的组件,使代码更容易维护测试和重用
3.总结
- MVC模型主要用于Django框架中,通过将应用程序分为模型、模板和视图,提供了一种清晰的架构方案
- MVC模型则是一个通用的设计模式,广泛应用于各种类型的应用程序中
- 无论使用哪种模型,都能够帮助开发者更好的组织和管理代码,并实现可扩展和可维护的应用程序
四.多对多三种创建方式
1.全自动
利用ORM自动帮我们创建第三张表关系
class Book(models.Model):
name = models.CharField(max_length=32)
# 全自动
authors = models.ManyToManyField(to='Author')
class Author(models.Model):
name = models.CharField(max_length=32)
- 优点
- 代码不需要自己写,非常方便,还支持ORM第三张表的方法
- 缺点
- 第三张关系表的扩展性极差(没办法添加额外字段)
2.纯手动(不建议使用)
class Book(models.Model):
name = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32)
class BookAuthor(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
- 优点
- 第三张表完全取决于自己进行额外的拓展
- 缺点
- 需要写的代码比较多
- 不能使用ORM提供的相关方法
3.半自动
class Book(models.Model):
name = models.CharField(max_length=32)
# 全自动
# through_fields : 当前表是谁,第一个参数就是谁
# 判断的本质:通过第三张表查询对应的表,需要用到哪个字段就把哪个字段放在前面
authors = models.ManyToManyField(to='Author', through='BookAuthor', through_fields=('book', 'author'))
class Author(models.Model):
name = models.CharField(max_length=32)
class BookAuthor(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
- 这样虽然可以使用ORM的正反向查询,但是没法使用add,set,remove,clear这四个方法