django03--请求生命周期、路由层
一 django请求生命周期流程图(必会)
# 每个人都要会画 这个图是你们后期复习django最好的一个梳理方式
1.用户在浏览器中输入url,发送一个GET方法的request请求。
2.Django中封装了socket的WSGi服务器,监听端口接受这个request 请求,再进行初步封装,然后传送到中间键中
3.中间件,对请求进行校验或处理
4.传输到路由系统中进行路由分发,匹配相对应的视图函数(FBV)
5.视图函数中,进行业务逻辑的处理,
6.调用modles中表对象,通过orm拿到数据库(DB)的数据。同时拿到templates中相应的模板进行渲染,
7.然后将这个封装了模板response响应传输到中间键中,依次进行处理
8.最后通过WSGi再进行封装处理,响应给浏览器展示给用户
# 扩展知识点
缓存数据库
提前已经将你想要的数据准备好了 你来直接拿就可以
提高效率和响应时间
当你在修改你的数据的时候 你会发现数据并不是立刻修改完成的
而是需要经过一段时间才会修改
二 路由层
1 路由匹配
# 路由匹配
路由: 即请求地址与视图函数的映射关系
# 基本格式
from django.conf.urls import url
urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
]
# 参数说明
正则表达式:一个正则表达式字符串
views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
参数:可选的要传递给视图函数的默认参数(字典形式)
别名:一个可选的name参数
# 匹配原则
从上往下 正则表达式能够匹配到内容,就算匹配成功
会立刻执行后面的视图函数,并且结束整个路由匹配过程
# 注意:
你在输入url的时候会默认加斜杠
django内部帮你做到重定向
第一次匹配不行
url后面加斜杠再来一次
# 取消自动加斜杠 (setting.py)
APPEND_SLASH = False/True # 默认为True 是自动加斜杠的
# eg:
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 首页
url(r'^$',views.home),
# 路由匹配
url(r'^test/$',views.test),
url(r'^testadd/$',views.testadd),
# 尾页(404页面) 放在路由匹配最下面,上面所有路径都匹配不到,会走这个
url(r'',views.error),
]
2 路由分组
分组:就是将路由层的某一段正则表达式用小括号扩起来,表示匹配到的内容是一个整体
2.1 无名分组
# 无名分组
就是将路由层括号内正则表达式匹配到的内容
当作 位置参数 传递给对应的视图函数
url(r'^test/(\d+)/',views.test)
def test(request,xx):
print(xx)
return HttpResponse('test')
2.2 有名分组
# 有名分组 将括起来的正则表达式 起一个别名
就是将路由层括号内正则表达式匹配到的内容
当作 关键字参数 传递给对应的视图函数
url(r'^testadd/(?P<year>\d+)',views.testadd)
def testadd(request,year):
print(year)
return HttpResponse('testadd')
2.3 无名有名能否混用
# 无名有名分组 不能混用
但是同一种分组可以使用N多次
# 单个分组情况下,可以重复使用
url(r'^index/(\d+)/(\d+)/(\d+)/', views.index),
url(r'^index1/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)/', views.index1),
def index(request,*args,**kwargs):
print(args)
return HttpResponse('test')
def index1(request,*args,**kwargs):
print(kwargs)
return HttpResponse('test')
3 反向解析
3.1 普通反向解析
反向解析:通过一些方法得到一个结果,该结果可以直接访问对应的url ,从而触发视图函数
# 简单理解:
给路由匹配取一个别名,通过别名的反向解析,能获取到对应的url,从而触发执行视图函数
# 在路由层书写路由与视图函数时,起一个别名
url('home/', views.home,name='home'),
# 反向解析
# 后端反向解析(需要导入reverse模块)
from django.shortcuts import render,HttpResponse,redirect,reverse
def home(request):
print(reverse('home')) # '/home/'
return render(request, 'home.html')
# 前端反向解析
<a href="{% url 'home'%}">111</a> # href='/home/'
3.2 无名分组反向解析
# 作用
通过反向解析的方式,将url分组匹配到的内容,当做位置参数,传递给视图函数,并触发执行
# 无名分组反向解析
url(r'^index/(\d+)/',views.index,name='xxx')
# 需要制定正则表达式匹配的参数
# 前端
{% url 'xxx' 123 %} # /index/123
# 后端
reverse('xxx', args=(1,)) # 注意是元祖的形式
# 注意:
这个数字写代码的时候应该放什么?
数字一般情况下放的是数据的主键值 数据的编辑和删除
url(r'^edit/(\d+)/',views.edit,name='xxx')
def edit(request,edit_id):
reverse('xxx',args=(edit_id,))
{%for user_obj in user_queryset%}
<a href="{% url 'xxx' user_obj.id %}">编辑</a>
{%endfor%}
3.3 有名分组反向解析
# 有名分组反向解析
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={'year':123}))
# 简便的写法 减少你的脑容量消耗 记跟无名一样的操作即可
print(reverse('ooo',args=(111,)))
# 总结:
有名/无名分组方向解析,只是路由层不同,反向解析时,统一记无名的形式即可
4 路由分发
"""
django的每一个应用都可以有自己的
templates文件夹
urls.py
static文件夹
也就意味着多人协同开发变得更加的简单了
"""
# 前提:
当一个django项目中的url特别多的时候 总路由urls.py代码非常冗余不好维护
此时利用路由分发 来减轻总路由的压力
利用路由分发之后 总路由不再干路由与视图函数的直接对应关系
而是做一个分发处理
识别当前url是属于哪个应用下的 直接分发给对应的应用去处理
# 总路由
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 1.路由分发 (需要导入app01和app02模块)
url(r'^app01/',include(app01_urls)), # 只要url前缀是app01开头 全部交给app01处理
url(r'^app02/',include(app02_urls)) # 只要url前缀是app02开头 全部交给app02处理
# 2.终极写法 推荐使用 (以字符串的形式,就不用导入app01和app02模块)
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))
# 注意事项:总路由里面的url千万不能加$结尾
]
# 子路由
# app01 urls.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^reg/',views.reg)
]
# app02 urls.py
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'^reg/',views.reg)
]
5 名称空间(了解)
# 当多个应用出现了相同的别名 我们研究反向解析会不会自动识别应用前缀?
正常情况下的反向解析是没有办法自动识别前缀的,
需自己带上名称空间,表明是哪个应用的
# 名称空间
# 总路由
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))
# 解析的时候
# app01
urlpatterns = [url(r'^reg/',views.reg,name='reg')]
# app02
urlpatterns = [url(r'^reg/',views.reg,name='reg')]
reverse('app01:reg')
reverse('app02:reg')
{% url 'app01:reg' %}
{% url 'app02:reg' %}
# 其实只要保证名字不冲突 就没有必要使用名称空间
一般情况下 有多个app的时候我们在起别名的时候会加上app的前缀
这样的话就能够确保多个app之间名字不冲突的问题
urlpatterns = [
url(r'^reg/',views.reg,name='app01_reg')
]
urlpatterns = [
url(r'^reg/',views.reg,name='app02_reg')
]
6 伪静态(了解)
# 静态网页
数据是写死的 万年不变
# 伪静态
将一个动态网页伪装成静态网页
# 为什么要伪装呢?
https://www.cnblogs.com/Dominic-Ji/p/9234099.html
伪装的目的在于增大本网站的seo查询力度
并且增加搜索引擎收藏本网上的概率
搜索引擎本质上就是一个巨大的爬虫程序
总结:
无论你怎么优化 怎么处理
始终还是干不过RMB玩家
# 正则加上 .html 后缀
urlpatterns = [
url(r'^reg.html',views.reg,name='app02_reg')
]
三 虚拟环境(了解)
# 虚拟环境
1.能够实现针对不同的项目配备专属的编程环境
该环境内只有该项目用到的模块 用不到一概不装
2.创建一个虚拟环境,就类似于重新下载了一个纯净的python解释器
但是虚拟环境不要创建太多,是需要消耗硬盘空间的
3.虚拟环境的唯一表示是venv文件夹
# pycharm中创建虚拟环境 记得要勾选--可用于所有项目
四 django版本区别
# 1.url方法
django1.X路由层使用的是url方法
django2.X和3.X版本中路由层使用的是path方法
url() # 第一个参数支持正则
path() # 第一个参数是不支持正则的 写什么就匹配什么
如果你不习惯使用path, 那么也给你提供了另外一个方法
from django.urls import path, re_path
re_path(r'^index/',index)
from django.conf.urls import url # 最好不要使用这种,因为这是1.x的方法
url(r'^login/',login)
2.X和3.X里面的re_path <==> 1.X里面的url
# 2.虽然path不支持正则 但是它的内部支持五种转换器
path('index/<int:id>/',index)
# 将第二个路由里面的内容先转成整型,然后以关键字的形式传递给后面的视图函数
def index(request,id):
print(id,type(id))
return HttpResponse('index')
str # 匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int # 匹配正整数,包含0
slug # 匹配字母、数字以及横杠、下划线组成的字符串
uuid # 匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00
path # 匹配任何非空字符串,包含了路径分隔符(/) 不能使用?
# 3.除了有默认的五个转换器之外 还支持自定义转换器 (了解)
class MonthConverter:
regex='\d{2}' # 属性名必须为regex
def to_python(self, value):
return int(value)
def to_url(self, value):
return value # 匹配的regex是两个数字,返回的结果也必须是两个数字
from django.urls import path,register_converter
from app01.path_converts import MonthConverter
# 先注册转换器
register_converter(MonthConverter,'mon')
from app01 import views
urlpatterns = [
path('articles/<int:year>/<mon:month>/<slug:other>/', views.article_detail, name='aaa'),
]
# 4.模型层
1.X外键默认都是级联更新删除的
2.X和3.X中需要你自己手动配置参数
models.ForeignKey(to='Publish')
models.ForeignKey(to='Publish',on_delete=models.CASCADE...)