django(模型层)
模型层(ORM语法):跟数据库打交道
单表查询(增删改查)
django自带的sqlite3数据库对日期的格式不是很敏感,处理时候容易出错
脚本代码无论是写在应用下的test.py还是自己单独开设py文件都可以
测试脚本
当你只是想测试django的某一个py文件类容,那么你可以不用书写前后端交互
的形式,而是直接写一个测试脚本即可
测试环境的准备 去manage.py中拷贝前四行,然后自己写两行
import os
import sys
if __name__ == "__main__":
os.evrion.setdefault ("DJAGO_SETTING_MODULE" ,"项目名.settings" )
import django
django.setup()
在代码块的下面就可以测试django里面的单个py文件
增
model.表名.objects.create( 字段 = 值 )
user_obj = model.表名( 字段 = 值 )
user_obj . save()
删
model.表名.objects.filter( pk = 值 ) . delete()
user_obj = model.表名.objects.filter( pk = 值 ) . first()
user_obj.delete()
修改
model.表名.objects.filter( pk = 值 ) . update( 字段 = 值 )
user_obj = model.表名.objects.get( pk = 值 )
user_obj.字段 = 值
user_obj.save()
DataField
DateTimeField
两个重要参数
auto_now: 每次操作数据的时候,该字段会自动将当前时间更新
auto_now_add: 在创建数据的时候会自动将当前创建的时间记录下来,之后只要
不认为的修改,那么就一直不会
pk会自动查找当前表的主键字段,指代的就是当前表的主键字段
用pk之后,你就不需要指代当前表的主键字段是什么
get方法返回值就是当前数据对象
但是方法不推荐使用,一旦数据不存在该方法就会直接报错
而filter则不会,所以我们还是用filter
查看内部sql语句的方式
方式1
res = model.表名.objects.values_list(字段)
print( res.query )
查看内部封装的sql语句
查看sql语句的方式,只能用于queryset对象
只有queryset对象才能够点击query查看内部的sql语句
方式2
所有的sql语句都能查看
去配置文件中配置一下即可
必知必会
1all() 查询所以
2filter() 带有过滤条件
3get() 直接拿数据对象 但是条件不存在直接报错
4first() 拿queryset里面的第一元素
5last()
6values() 可以指定获取的数据字段( 列表套字典 )
7value_list() (列表套元组)
8distinct() 去重(一定要是一模一样)
9order_by() 排序
10reverse() 反转的前提是数据已经排过序
11count() 统计当前数据的个数
12exclude() 排除在外
13exists() 判断是否存在
神奇的双下划线查询
__gt 大于
__lt 小于
__gte 大于等于
__lte
__in 或者
__range 在一个区间
__contains 包含 __icontains 忽略大小写
__startswith
时间相关
__month
__year
一对多外键字段的增删改查
多对多外键字段的增删改查 就是在操作第三张表
add给第三张关系表添加数据
括号内既可以传数字也可以传对象,并且都支持多个
remove
括号内既可以传数字也可以传对象,并且都支持多个
set
括号内 必须填一个可迭代对象,该对象既可以数字也可以对象并且支持多个
clear
括号不要加任何参数
正反向的概念
正向:看外键字段在我手上,我查你就是正向
方向:看外键字段不在我手上,我查你就是正向
正向查询按外键字段,反向查询按表名小写加_set
多表查询
子查询(基于对象的跨表查询)
联表查询(基于双下滑线的跨表查询)
在书写orm语句的时候跟写sql语句一样的
不要企图一次性将orm语句写完,如果比较复杂,就写一点看一点
正向需要加.all
当你的结果可能有多个的时候就需要加.all()
如果结果是一个则直接拿到数据对象
当你的查询结果可以有多个的时候,就必须加_set.all()
如果结果只有一个的时候,不需要加
django orm中
1基于对象的跨表查询
子查询
先拿到一个数据对象
对象点点
2基于双下划线的跨表查询
联表查询
聚合查询(聚合函数的使用)aggregate
聚合查询通常情况下都是配合分组一起使用的
只要跟数据库相关的模块,基本上都在djangon.db.models
如果上述没有,那么应该在django.db里面
分组查询(group by的使用)annotate
model.book.objects.annotate( 别名 = 聚合函数( 字段 ) ).values(字段)
只要你的orm语句得出的结果还是一个queryset对象
那么它就可以继续无限制的点queryset对象封装的方法
F与Q查询
F查询
能够帮你直接获取到表中的某个字段对应的数据
Q查询
filter括号内多个参数是and的关系
Q包裹逗号分隔还是and的关系
| or关系
~ not关系
Q的高阶用法
我们之前在查询数据的时候,条件的左边都是变量名的形式
q = Q()
q.connector = 'or'
q.children.appened ( ( '字段' ),值 )
filter( q )
django中如何开启事务
事务四大特征
ACID
原子性:不可分割的最小单位
一次性:跟原子性是相辅相成
隔离性:事务之间相互不干扰
持久性:事务一旦确认永久生效
事务的回滚 rollback
事务的确认 commit
数据库三大设计范式
第一范式:确保每列的原子性
第二范式:目标是确保表中的每列都和主键相关.
第三范式:目标是确保每列都和主键列直接相关,而不是间接相关.
目前你只需要掌握django中如何简单开启事务
from django.db import transaction
try:
with transacton.atomic():
sql1
except Exception as e:
print( e )
orm中常用字段及参数
AutoField 主键 primary-key = True
CharField verbaose_name 字段注释 max_length 长度
IntegerField
DecimalField max_digits decimal_place
EmailField
DateField auto_now:修改 auto_now_add:新建
DatetimeField
BooleanField 布尔值
TextField 文本类型 该字段可以用来存大段类容(文章、博客...)没有字数限制
FileField
外键字段及参数
unique = True
ForeignKey( unique = True ) == OnetoOneField( )
to
to_field
db_index 设置关联字段 默认不写关联的就是另外一张表的主键字段
on_delete 删除关联表中的数据
django 2.x版本以上,需要你自己绑定外键字段的级联更新删除
数据库查询优化
only与defer
orm语句的特点:
惰性查询,如果你仅仅书写的orm语句,在后面的根本没有用到该语句所查询
处理的参数,那么orm会自动识别,直接不执行
点击only括号的字段,不会走数据库
点击only括号内没有的字段,会重新走数据库查询而all不需要走
defer 与 only刚好相反
defer括号内放的字段不在查询出来的对象里面,查询该字段需要重新走数据库
而如果查询的是非括号内的字段,则不需要走数据库
select_related与prefetch_related 跟跨表操作有关
select_related括号内只能放外键字段 一对一 一对多
括号内只能放外键字段并且多对多不信
将联表后的结果全部查询结果封装到对象里面
之后对象在点击表中的字段的时候都无需最走数据库
prefetch_related 该方法内部其实就是子查询
redirect括号内可以直接写url,其实也可以写别名
如果你的别名需要额外给参数的话,那么必须使用reverse解析
choices参数(数据库字段设计)
只要某个字段的可能性是可以列举完全的,那么一般情况下采用choices参数
只要是choices参数的字段,如果你想要获取对应信息,固定写法 get_字段_display()
MTV与MVC模型
django号称是MTV模型
M:models
T:templates
V:views
其实django本质也是MVC
M:models
V:views
C:controller( urls.py )
多对多关系的三种创建方式
全自动:利用orm自动帮我们创建第三张关系表
authors = models.ManyToManyField( to = 'Author')
优点:代码不需要你写,非常方便,还支持orm提供操作第三张关系表的方法
不足之处:第三张关系表的扩展性极差( 没有办法额外添加字段 )
纯手动
class Book2Author( models.Model ):
book_id = models.ForeignKey( to = ' Book ' )
author_id = models.ForeignKey( to = 'Author ' )
优点:第三张完全取决于你自己进行额外的扩展
不足之处:需要写的代码较多,不能够最使用orm提供的简单的方法,不建议使用
半自动
authors = models.ManyToManyField( to = 'Author',
through = 'Book2Author',
through_fields = ( ' book ' , ' author '))
through_fields字段先后顺序,判断的本质,通过第三张表查询对应的表,需要用到哪个
字段就把哪个字段放在前面
可以使用orm的正反向查询可以用,但是无法使用add,set,remove,clear这四个方法