目录
django之路由层
django请求生命流程
客户端(浏览器)发送请求,经过web服务网关接口进入django后端,首先经过django中间件的处理,然后到达路由层,进行路由匹配,匹配到的进入视图层调用视图函数或者视图类,函数再调用模板层或者调用模型层数据库,最终再返回到中间件,从中间件返回到web网关,在返回到浏览器或者客户端
路由匹配
django2.x及以上 path第一个参数写什么就匹配什么
django1.x path第一个参数是正则表达式
无论什么版本的django都自带路由自动加斜杠后缀的功能
转换器
正常情况下很多网站都会有很多相似的网址,如果我们每一个都单独开设路由不合理
django2.x及以上版本路由动态匹配的转换器是有多种的
常用:str:匹配除路径分隔符外的任何非空字符串
int:匹配0或者任意正整数
注意:这里的匹配是关键字传参,str后面跟的什么,传参就要写什么,函数的参数除了request,还要有str后面紧跟着的参数
正则匹配
无名分组
就是正则匹配加括号没有起别名,传参方式是位置传参,变量名无所谓
有名分组
正则匹配加括号中用?P<别名>,这样的方式给正则分组起别名,传参方式是关键字传参,函数形参要与别名一致
反向解析
通过一个名字可以解析出来一个结果,该结果可以访问到某个对应的路由
也就是我们给路由起一个简单的名字,我们可以通过反向解析这个路由的别名得到路由的地址,最终访问路由即可
基本使用
1.;路由匹配关系起别名
path('index',views.index,name='index_func')
html页面使用:{%url 'index_func' %}
后端使用reverse('index_func')
动态路由的反向解析
动态路由需要给动态变化的内容,才能够解析
path('index/<int:id>/',views.index,name='index_func')
html页面使用:{% url 'index_func', 1 %}
后端使用:reverse('index_func',ages=(1),)
路由分发
django支持每个应用都可以用自己独立的路由层、静态文件、模板层,基于该特性多人开发项目就可以实现
多个应用都有很多路由与视图函数的对应关系,这个时候可以拆分到各自的路由层中
使用路由分发钱,总路由直接参与路由与视图函数的匹配
使用路由分发后,总路由只按照应用名分配匹配方向
名称空间
问题:路由分发之后,针对相同的别名默认情况下是无法识别应用前缀的
解决办法:别名不冲突即可,在别名之前加上应用的名字
django视图层
视图层之不会三板斧
HttpResponse:返回字符串到前端页面
render:返回html页面
redirct:重定向,返回一个网页地址
用来处理请求的视图函数都必须返回HttpResponse对象 完全正确
查看HttpResponse源代码,实际上他是一个类,那我们在返回的时候,类加括号,就是产生了一个对象,实际上就是返回的对象
查看render源代码,他实际上是一个函数,但是函数的返回值是HttpResponse加括号,所以实际上还是返回的HttpResponse对象
查看redirct源代码,也是一个函数,但是在函数体代码中,有产生一个类,类的继承祖先其实就有HttpResponse,所以最终还是这个类的对象
JsonResponse对象
主要作用是直接将我们的数据格式转换成json格式发送到页面,不需要使用json模板先转json字符串再发到前端页面
视图层之request对象获取文件
form表单携带文件类型的数据需要做到以下几点:
1.method必须是post类型 get请求最多携带的数据大小是2kb
2.enctype必须是mulitipart/form-date
django后端需要通过request.FILES获取文件类型的数据
拿到文件数据
date = request.FILES.get('文件名')
视图层之FBV与CBV
FBV
基于函数的视图
需要在函数体代码中做if判断是POST还是GET
CBV
基于类的视图
在类中定义post和get两个绑定给对象的方法,会根据请求方法的不同自动匹配对应的方法并执行
CBV源码剖析
从路由层出发,先看路由层写法的不同
path('login/',views.Mylogin.as_view())
1.我们首先看到CBV与FBV的路由层写法不同,多一个as_view()
2.我们首先回顾类的知识,一个类点了一个名字加括号,那么这个肯定是点了一个方法,函数名加括号执行优先级最高,项目运行路由的这个函数肯定会优先运行,所以我们要看一下这个方法是什么
3.查看源代码,我们发现这个方法是绑定给类的方法,那么我们的类点了这个方法会直接将我们创建的类作为第一个参数传入,在这个方法内部有一个类加括号产生一个对象,那么就是我们所写的类产生的对象,最终返回是一个类点一个dispatch方法
4.回顾对象查找名字的顺序,首先在对象名称空间,在到产生对象的类,最后到类的父类,我们发现对象和类都没有,那么我们到产生对象的父类中寻找,就找到了这个方法
5.这个方式主要作用是判断request.method方法属于不属于8种请求方法里面,如果是的话,用反射的方式,将请求方法的大小转为小写,获取对应函数的函数体代码,返回加括号执行,最终就是执行我们所写的get或者post函数
回顾:getattr:获取在类中字符串对应的数据的值或者函数体代码,可以赋值给另一个变量名,打印变量名就可以获得数据的值,或者变量名加括号就可以执行字符串对应的函数体代码
django之模板层
模板层的语法
模板层的两种语法:
{{}}:主要与数据值有关
{% %}:主要与逻辑相关
1.针对需要加括号调用的名字,django模板语法会自动加括号调用
2.模板语法的注释前端浏览器是无法查看的
1.模板语法的传值
精准传值{'n':name} 在模板层n就指代name的值
locals() 将函数名称空间中所有的名字全部传递
2.模板语法传值特性
基本数据类型正常显示
文件对象也可以展示并调用
函数名会自动加括号执行并将返回值展示到页面上
类也会自动加括号调用,也就是产生了一个该类的对象
对象不会加括号
模板语法之过滤器
{{值|default}} 如果没有值就显示nothing
{{值|length}} 返回值的长度
{{值|fileziseformat}} 将值格式转化为合适的文件尺寸
{{值|date:'Y-m-d'}} 将时间格式化输出位年-月-日
{{值|safe}} 告诉模板可以转义这个值
模板层之标签
if条件:
{% if 条件1 %}
条件成立执行的
{% elif 条件2 %}
条件成立执行的
{%else%}
条件都不成立执行的
for标签:
{% for k in t1%}
关键:forloop.first 第一次循环
forloop.last 最后一次循环
模板的继承
模板的继承
多个页面有很多相似的地方,我们可以采取下列方式
模板的继承:
{% extends '模板名字' %} 表示继承模板中全部
划定可以修改区域
{% block 名字%}
{% endblock % }
使用划定的区域
{% block 名字%}
{% endblock %}
django模型层
ORM常用关键字
create 写入数据
filter 根据条件筛选数据,结果是queryset对象 [对象1,对象2]
filter().first() 获取结果集的第一个对象,通常用于精准得到某一个对象之后,从queryset对象拿出来
filter().last() 获取结果集的最后一个对象
update() 更新数据,批量更新
filter().update() 指定查询到的某一个记录进行更新
delete() 删除数据,批量删除
filter().delete() 指定查询到的某一个记录进行删除
all() 获取所有数据,相当于filter括号内什么都不写
values() 根据指定字段名获取数据值,结果是queryset对象[{字段名:数据值}]
values_list() 根据指定字段名获取数据,结果是queryset对象,列表套元组,不显示字段名
distinct() 去重数据要一模一样才可以,如果有主见参与肯定是不可以的,所以一般搭配values(字段名).distinct 根据某一个字段去重
order_by 根据指定条件排序,默认是升序
神奇的双下划线查询
__gt= 大于
__lt= 小于
__gte= 大于等于
__lte= 小于等于
__in=() 或者,多个参数,多个参数其实一个符合即可
__range=(两个参数) 两参数范围之内包含这两个参数
__contains 模糊查询,区分大小写
__icontains 模糊查询,不区分大小写
__year 时间截取
ORM外键字段的创建
"""
复习SQL语句外键关系
一对一
外键在查询频率高的一方
一对多
外键在多的一方
多对多
外键在第三张表
"""
ORM外键关系:
一对一
外键在查询频率高的一方,关键字OneToOnefiled(to='表名',on_delete=models.CASCADE)
一对多
外键在多的一方
关键字:ForeiKey(to='表名',on_delect=models.CASCADE)
多对多
外键在查询频率高的一方,是一个虚拟外键,ORM会自动创建第三张表
关键字:ManyToManyField(to='表名')
数据插入
考虑外键的关系,要先插入没有外键的表,在插入相关联的表,否则是无法插入的
针对数据插入:
外键名_id=对应表的主键
外建名=对应表的对象
多对多添加数据值
1.先产生主键所在记录的对象
2.对象点外键.add() 放主键值,也可以放对象
多对多修改数据
对象.外键.set() 括号内必须是列表或者元组
多对多清除数据关系
对象.外键.clear() 括号内什么都不用写
ORM跨表查询
"""
复习MySQL跨表查询的思路
子查询
分布操作:将一条SQL语句用括号括起来当做另外一条SQL语句的条件
连表操作
先整合多张表之后基于表单查询即可
inner join
"""
正反向查询的概念:
正向查询
由外键字段所在的表数据查询关联的表数据
反向查询
没有外键字段的表数据查询关联的表数据
ps:正反向的核心就看外键字段在不在当前数据表中
ORM跨表查询的口诀
正向查询按外键字段
反向查询按表名小写
基于对象的跨表查询
1.查询主键为1的书籍对应的出版社名称
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish.name)
2.查询主键为4的书籍对应的出版社名称
book_obj = models.Book.objects.filter(pk=4).first()
print(book_obj.authors.all().values('name'))
3.查询主键为4的书籍对应的出版社名称
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.authordate.phone)
4.查询东京出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='东京出版社').first()
print(publish_obj.book_set.all().values('name'))
"""出版社出的书是多个的,所以要用__set.all()获取全部"""
5.查询jason写过的书籍
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.book_set.all().values('name'))
6.查询电话号码是119的作者姓名
phone_obj = models.Authoredate.objects.filter(phone='119').first()
print(phone_obj.author.name)
总结:如果查到的数据是多个就要用__set和all如果不是就不需要
基于双下划下的跨表查询
1.查询主键为1的书籍对应的出版社名称
res = models.Book.objects.filter(pk=1).values('publish__name')
print(res)
2.查询主键为4的书籍对应的出版社名称
res = models.Book.objects.filter(pk=4).values('authors__name')
print(res)
3.查询主键为4的书籍对应的出版社名称
res = models.Author.objects.filter(name='jason').values('authordate__phone')
print(res)
4.查询东京出版社出版过的书籍
res = models.Publish.objects.filter(name='东京出版社').values('book__name')
print(res)
5.查询jason写过的书籍
res = models.Author.objects.filter(name='jason').values('book__name')
print(res)
6.查询电话号码是119的作者姓名
res = models.Authoredate.objects.filter(phone='119').values('author__name')
print(res)
进阶操作
1.查询主键为1的书籍对应的出版社名称
res = models.Publish.objects.filter(book__pk=1).values('name')
print(res)
2.查询主键为4的书籍对应的出版社名称
res = models.Author.objects.filter(book__pk=4).values('name')
print(res)
3.查询主键为4的书籍对应的出版社名称
res = models.Authoredate.objects.filter(author__name='jason').values('phone')
print(res)
4.查询东京出版社出版过的书籍
res = models.Book.objects.filter(publish__name='东京出版社').values('name')
print(res)
5.查询jason写过的书籍
res = models.Book.objects.filter(authors__name='jason').values('name')
print(res)
6.查询电话号码是119的作者姓名
res = models.Author.objects.filter(authordate__phone='119').values('name')
print(res)
补充操作
查询主键为4的书籍对应的作者的电话号码
"""获得数据对象查"""
res = models.Book.objects.filter(pk=4).values('authors__authordate__phone')
print(res)
"""获取详情对象开始"""
res = models.Authoredate.objects.filter(author__book__pk=4).values('phone')
print(res)
"""从中间的作者对象"""
res = models.Author.objects.filter(book__pk=4).values('authordate__phone')
print(res)
"""
以上三种办法都可以,从获得不同的对象开始,从第一个对象开始我们用values顺序进入表中,从最后一个对象开始我们使用filter倒着进入表中,从中间的表开始就需要我们先倒着获得我们先想要的对象然后再顺着获得我们想要的数据值
"""
标签:第十二,总结,name,res,查询,filter,__,路由
From: https://www.cnblogs.com/zhanghong1229/p/16990458.html