04无名有名分组的反向解析、路由分发、名称空间、伪静态、虚拟环境、django1.x、2.x的区别、视图层、三板斧、jsonResponse、form表单上传文件、FBV与CBV
(视图函数可以是函数可以是类)
回忆
数据的编辑和删除
# 查询所有数据
res = models.User.objects.filter()
res = models.User.objects.all()
# 编辑数据
1、首先获取用户想要的编辑数据主键值
url?edit_id=1
url/1/
2、后端查询出对应的数据对象展示到前端
利用input标签的value属性
3、提交post请求修改数据
前期提交post请求一定要先去配置文件里去注释掉一行(csrf。。。。)
如果不注释会报403错误
# 批量更新
models.User.objects.filter(id=edit_id).update(**kwargs)
# 单个各更新
user_obj = models.User.objects.filter(id=edit_id).first()
user_obj.username = 'kb'
user_obj.password = '123'
user_obj.save()
该方法当字段比较多的时候效率会降低很多
因为他是从头到尾将数据所有的字段重写一遍
# 删除数据
数据并不会真正意义上的删除,我们会在创建表的时候会加一个用来标识是否被删除的字段
is_delete
is_alive
is_status
删除数据其实就是修改字段的状态,之后通过代码筛选出没有删除状态的数据即可
# 删除数据的时候应该有一个二次确认的环节 而不是应该直接删除
ajax讲完之后加二次确认结合sweetalaert
"""
图书管理系统表设计(orm创建表关系)
"""
一对多、:models.Foreignkey(to='关联表名');不加引号的情况下关联的表名必须在上方
1、在django 1.x版本中外键默认就是级联更新删除的
2、会自动给字段加_id后缀 无论你有没有加(自己不要加)
(外键字段建在多的一方)
多对多、:models.ManyToManyField(to='关联表名')
1、在django 1.x版本中外键默认就是级联更新删除的
2、该字段是一个虚拟字段不会真正的在表中展示出来而是用来告诉django orm当前表和关联表是多对多的外键关系 需要自动创建第三张关系表
(建在任意一方都可以;但是要优先建在频繁使用的一方)
一对一、:models.OneToOneField(to='关联表名')
1、在django 1.x版本中外键默认就是级联更新删除的
2、会自动给字段加_id后缀 无论你有没有加(自己不要加)
(建在任意一方都可以;但是要优先建在频繁使用的一方)
(判断表关系的方式:换位思考)
"""
django请求生命周期流程图
"""
发送请求(HTTP协议)
web服务端网关接口
1、请求来的时候解析封装
响应走的时候打包
1、django默认的wsgiref模块不能承受高并发 最大只有1000左右
上线之后会替换成uwsgi来增加并发量
3、WSGI跟wsgiref和uwsgi是什么关系
WSGI是协议
wsgiref和uwsgi是实现协议的功能模块
django后端
1、django中间件(暂时不考虑 后面再了解)
类似于django的保安
2、urls.py 路由层
识别路由匹配对应的视图函数
3、views.py 视图层
网站整体的业务逻辑
4、templates文件夹 模板层
网站所有的html文件
5、models.py 模型层
额外扩展:缓存数据库的作用(先去缓存中找缓存没有再去数据库回来丢进去一份)
"""
路由分发
"""
url()方法第一个参数是正则表达式
一旦匹配成功 就不会往下走了 而是直接触发正则后面的视图函数的运行
url(r'^admin/',....)
url(r'^$',....)
url(r'',....);404,通吃
# django路由匹配的时候其实可以匹配两次 第一次如果url后面没有加斜杠 django就会让浏览器加斜杠再发送一次请求
APPEND_SLASH = True/False
有名无名分组
# 无名分组
url(r'^index/(\d+)/',view.index)
将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数
index(request,111)
# 有名分组
url(r'^index/(?p<year>\d+)/',view.index)
将括号内正则表达式匹配到的内容当做关键字参数传递给后面的视图函数
index(request,year=111)
# 无名和有名不能混合使用
# 单个分组可以重复使用
url(r'^index/(\d+)/(\d+)/(\d+)/',view.index)
反向解析
"""
本质:通过一些方法得到一个结果 该结果可以访问到对应的url从而触发函数的运行
# 最简单的情况;第一个参数里边没有正则符号
url(r'^index/',view.index,name='xxx')
{% url 'xxx' %}
from django.shortcuts import reverse
reverse('xxx')
"别名不能出现冲突!!!!!"
内容概要
- 无名有名分组的反向解析
- 路由分发
- 名称空间(了解)
- 伪静态(了解)
- 虚拟环境(了解)
- django1.x和2.x的区别(了解)
-
视图层
- 三板斧
- jsonResponse
- form表单上传文件
- FBV与CBV(视图函数可以是函数可以是类)
内容详细
无名有名分组的反向解析
# 无名分组反向解析
url(r'^index/(\d+)/',views.index,name='xxx')
{% url 'xxx' 123 %}
reverse('xxx', args=(1,))
这个数字写代码的时候应该放什么
数字一般情况下放的是数据的主键值 利用它做数据的编辑和删除
必须要成的
利用无名有名分组 反向解析 完成数据的增删改查
"""
有名分组的反向解析
# 有名分组反向解析
url(r'^func/(?p<year>\d+)/',views.func,name='ooo')
<a href="{ % url 'ooo' year=123 % }">111</a> 了解
<a href="{ % url 'ooo' 123 % }">222</a> 记忆
# 有名分组反向解析 写法1 了解
print(reverse('ooo',kwargs={'tear':123}))
# 简单写法;记和无名一样操作即可
print(reverse('ooo',args=(111,)))
路由分发
"""
django的每一个应用都可以有自己的templates文件夹 urls.py static文件夹
正式基于上述特点 django能够非常好的做到分组开发(每个人只写自己的app)
作为组长 只需要将手写写的app全部拷到一个新的django项目中 然后配置文件里面注册所有的app再利用路由分发的特点将所有的app整合起来
当一个django项目中的url特别多的时候 总路由urls.py代码非常冗余不好维护
这个时候也可以利用路由分发来减轻总路由的压力
利用路由分发之后 总路由不再干路由与视图函数的直接对应关系
而是做一个分发处理
先识别当前的url是属于哪个应用下的直接分发给对应的应用去处理
1、创建应用:startapp app02
2、去sesettings.py里边注册 INSTALLED_APPS(app02)
2.1、自己创建一个urls.py (把总路由的代码拷进去)
3、先导入一个方法include
一方法、总路由导进来两个 from app01 import urls as app01_urls (防止冲突起别名)
from app01 import urls as app02_urls
写上两个url
# 路由分发
url(r'^app01/',include(app01_urls)),
url(r'^app01/',include(app02_urls))
# 只要是url前缀app01开头的 全部交给app01处理
# 只要是url前缀app02开头的 全部交给app02处理
---------------------------------------
二方法、# 终极写法推荐使用
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))
# 注意:总路由一定不能加$符结尾; 就直接写死了加上之后后边的东西就匹配不上了
三子路由:
# app01 urls.py
from django.conf.urls import url
from app01 import views
urpatterna = [
url(r'^reg/',views.reg)
# appo2 urls.py
from django.conf.urls import url
from app02 import views
urpatterna = [
url(r'^reg/',views.reg)
# 总路由一定不能加$ 加了就写死了后边的就匹配不到了
名称空间(了解)
# 当多个应用 出现了相同的别名 我们研究反向解析会不会自动识别应用的前缀
正常情况下的反向解析是没有办法自动识别前缀的
# 名称空间 namespace='app01' namespace='app02'
# 总路由
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))
# 解析的时候
# app01
urpatterna = [
url(r'^reg/',views.reg,name='reg')
# app02
urpatterna = [
url(r'^reg/',views.reg,name='reg')
reverse('app01:reg')
reverse('app02:reg')
{ % url 'app01:reg' % }
{ % url 'app02:reg' % }
# 其实只要保证名字不冲突 就没有必要使用名称空间
一般情况下 有多个app的时候我们在起别名的时候会加上app前缀
这样的话就能够确保多个app之间名字不冲突的问题
"""
伪静态(了解)
"""
数据是写死的 万年不变
将一个动态网页伪装成 静态网页
为什么要伪装?
伪装的目的在于增大本网站的seo查询力度
并且增加搜索引擎收藏本网上的概率
搜索引擎本质就是一个大的爬虫程序
# reg.html
urpatterna = [
url(r'^reg.html',views.reg,name='app01_reg')
]
虚拟环境(了解)
"""
在正常开发中 我们会给每一个项目配备一个独有的解释器环境
该环境内只有该项目用到的模块 用不到的一概不装
虚拟环境就类似于是一个单独的解释器环境
每创建一个虚拟环境就相当于从新下了一个纯净的python解释器
但是虚拟环境不要创建太多 会占用硬盘空间的
每一个项目都需要用到很多模块 并且每个模块版本还可能不一样
那么该如何让安装呢?
开发当中我们会给每一个项目配备一个requirements.txt文件
里面书写了该项目所有的模板既版本
你只需要直接输入一条命令 即可一键安装所有模块及版本
"""
django版本区别
"""
区别一:django1.x 路由层使用的是url方法
而在 django2.x 和3.x 版本使用的是path方法
url 支持正则
path 不支持正则 写什么就匹配什么(可以导入re_path 就支持正则了;就相当于1.x 的url)
虽然path不支持正则 但是他内部支持五种转换器
"""
区别、
模型层里面 1.x外键默认都是级联更新级联删除
但是到了2.x和3.x里面需要你手动自己删除
models.ForeignKey(to='Publish')
models.ForeignKey(to='Publish',on_dekete=modela.CASCADE..)
"""
视图层
"""
HttpResponse ------ 返回字符串
render ------------- 返回html页面 在返回给浏览器之前还可以给html文件传值
redirect ----------- 重定向
# 视图函数必须要返回一个HttpResponse对象 正确 研究三者源码即可得出结论
render 简单的内部原理
jsonResponse 对象
"""
json格式的数据有什么用?
前后端数据交互的时候需要json过度 跨语言数据传输
前端的序列化 后端的序列化
JSON.stringify() json.dumps()
JSON.parse() json.loads()
# json模块的
ensure_ascii=True(内部会自动帮你转码 改成False就不会转码了)
# 让你给前端浏览器返回一个json格式的字符串
import pickle
# 支持的数据类型 python中所有数据类型
# 序列化出来的结果看不懂 是二进制数据
# pickl序列化出来的数据只能在python中使用
#JS中如何序列化
JSON.stringify():序列化
JSON.parse():反序列化
** 在形参(定义)中:接收多余的关键字参数
** 在实参(调用)中:把字典打散成关键字
jsonResponse
# 只能序列化字典序列化其他的要加参数
from django.http import JsonResponse
在函数里直接返回 return JsonResponse(字典)# 直接帮你序列化返回前端页面
查看源码内部原理还是json模块 # 字典
return JsonResponse(字典,json_dumps_params={ensure_ascii=False})
return JsonResponse(列表,safe=False)
form表单上传文件及后端如何操作
# 注释掉 MIDDLEWARE 里csrf 的 一行
form表单上传文件类型的数据
1、method必须指定成post--------必须加上
2、enctype必须换成formdata ------- 必须加上
def ab_file(request):
if request.method == 'POST':
print(request.POST) # 只能拿到普通的键值对数据 文件数据拿不到
print(request.FILES) # 获取文件数据
file_obj = request.FILES.get('file') # 文件对象
print(file_obj.name)
with open(file_obj.name,'wb')as f:
for line in file_obj.chunks(): # 推荐加上chunks方法其实加不加一样都是一行行读取
f.write(line)
return render(request,'from.html')
request对象方法
"""
request.method ----- 用来获取请求方式
request.PPOST ----- 用来获取普通键值对数据 不包括文件
request.GET ----- 用来获取GET请求
request.FILES ----- 用来获取文件
request.path (path_info)------------ 只能拿到路由
request.get_full_path ------- 能够获取完整的url 以及问好后面的参数
request.body --------------- 原生的浏览器发过来的二进制数据
"""
FBV与CBV
# 视图函数既可以是函数也可以是类
# FBV
def index(request):
return HttpResponse('index')
# CBV
url(r'^login/',views.MyLogin.as_view())
2、后端views里先导一个模块
from django.views import View
class MyLogin(View):
def get(self,request):
return HttpRespons("get方法")
def post(self,request):
return HttpRespons("post方法")