django学习笔记
今日内容概要
- django请求生命周期流程图
- 路由层
今日内容详细
django请求生命周期流程图
整体概括请求的走向以及django的核心组成部分,参考下图。
1.浏览器发送一个基于HTTP协议的请求
2.进入web服务网关接口将请求来的数据拆解成一个request大字典
3.进入django框架里的中间件,相当于保安负责django安全性
4.进入django后端路由层完成功能匹配
5.进入视图层执行核心业务逻辑
6.执行核心业务逻辑的时候可能需要用到html页面,这时候就需要用到模板层
7.用模板的时候也可能用到数据库的数据,这时候用到模型层,由模型层帮你去跟数据库交涉
8.由orm把数据库返回的数据封装成一个数据对象,返回到视图层做一个模板语法,模板渲染
9.由视图层直接返回到中间件再做一层校验,怕携带危险数据
10.没问题会交给web服务网关接口封装数据发给浏览器
路由层
路由匹配
path('网址后缀',函数名)
只要网址后缀匹配上了就会自动执行后面的函数并结束整个路由的匹配。
1.路由结尾的斜杠
默认的情况下不写斜杠django会做二次处理,第一次匹配不上就会让浏览器自动加上斜杠再次请求。
django配置文件中可以指定是否自动添加斜杠:
APPEND_SLASH = False # 取消斜杠二次处理机制
2.path转换器
当网址后缀不固定的时候,可以使用转换器来匹配。
转换器类型 | 说明 |
---|---|
str | 匹配除了'/'之外的非空字符串 |
int | 匹配0或任何正整数,返回一个int |
slug | 匹配任意由ASCII字母或数字以及连字符和下划线组成的短标签 |
path | 匹配非空字段,包括路径分隔符'/' |
基本使用:
urls.py
path('func/<int:year>/<str:info>/', views.func)
views.py
def func(request,year,info):
pass
转换器匹配到的内容会当做视图函数的关键字参数传入,转换器有几个叫什么名字,那么视图函数的形参必须对应。
3.re_path正则匹配
re_path(正则表达式,函数名)
只要正则表达式能够从用户输入的后缀中匹配到内容就算匹配上了就会自动执行后面的函数并结束整个路由匹配。
re_patn('^test/$', views.test) #^是限制开头$是限制结尾
4.正则匹配之无名分组
re_path('^test/(\d+)/$', views.test)
路由匹配成功之后就会调用视图函数默认情况下会自动给视图函数传递一个request位置参数
def test(request):
return HttpResponse('测试')
如果路由匹配中使用括号对正则表达式进行了分组,那么在调用视图函数的时候,会将括号内匹配到的内容当做位置参数传递给视图函数。
# test(request,括号内正则表达式匹配到的内容)
例子:正则匹配到的内容是123
def test(request,123):
return HttpResponse('测试')
5.正则匹配之有名分组
re_path('^test/(?P<year>\d+)/(?P<others>.*?)/', views.test)
给括号内的正则表达式起别名之后,匹配成功则会讲括号内匹配到的内容按照关键字参数传递给视图函数。
# testadd(request,user_id=括号内正则表达式匹配到的内容)
例子:正则匹配到的内容是123
def test(request,user_id=123):
return HttpResponse('测试')
两者是否可以混合使用?
url(r'^test/(\d+)/(?P<year>\d+)/$', views.testadd) # 不可以 无名有名分组不能混合使用!!! 单个可以重复使用
url(r'^test/(\d+)/(\d+)/$', views.testadd) # 可以
url(r'^test/(?P<a>\d+)/(?P<b>\d+)',views.testadd) # 可以
6.django版本区别
django1.11中,只支持正则匹配并且方法是url()
django2,3,4中,方法是path(), re_path()等价于url()
反向解析
a标签的href可以写网址的全称,也可以写后缀。
href='https://www.baidu.com'
href='/login/' # 自动补全当前服务的ip和port href='127.0.0.1:8000/login/'
页面上有很多a标签链接了其他路由,一旦路由发送变化会导致所有页面相关链接失效。
为了防止出现该问题,我们需要使用反向解析
反向解析:返回一个结果,该结果可以访问到对应的路由。
步骤一:路由对应关系起别名
path('register/', views.reg, name='reg_view')
步骤二:使用反向解析语法
html页面:
{% url 'reg_view' %} # reg666/ 结果可以访问路由
例子:<a href="{% url 'reg_view' %}">reg_view</a>
后端:
from django.shortcuts import reverse
reverse('reg_view') # reg666/ 结果可以访问路由
ps:反向解析的操作三个方法都一样 path() re_path() url()
无名有名反向解析
步骤一:路由对应关系起别名
path('reg/<str:info>/', views.reg, name='reg_view')
步骤二:使用反向解析语法
当路由中有不确定的匹配因素,反向解析的时候需要人为给出一个具体的值
html页面:
{% url 'reg_view' 'jason' %}
后端:
from django.shortcuts import reverse
reverse('reg_view', args=('jason',))
路由分发
如果一个django项目特别庞大,里面有很多应用,每个应用下有很多对应关系。那么django自带的路由层里面的代码就会非常非常的多。
我们可以根据应用的不同拆分路由对应关系到不同的应用中。django支持每个应用都可以有自己独立的路由层、模板层、静态文件、视图层(默认)、模型层(默认)。所以所有人都可以在应用中开发完整的项目功能,最后汇总到一个空的django项目中,然后通过路由分发整合所有人的应用。
路由分发的作用:能够让基于django开发的多个应用完全独立,便于小组开发
1.创建多个应用,并去配置文件中注册
INSTALLED_APPS = [
'app01',
'app02'
]
2.路由分发:总路由
# 正规写法
from django.urls import path, include
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
path('app01/',include(app01_urls)),
path('app02/',include(app02_urls))
]
# 简便写法
# 同名文件夹下urls.py文件内
from django.urls import path, include
urlpatterns = [
path('app01/', include('app01.urls')),
path('app02/', include('app02.urls')),
]
3.子路由
# app01应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after) # app01
]
# app02应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after) # app02
]
应用场景:当项目特别大,应用特别多的时候,可以使用路由分发,非常方便。
名称空间
在路由分发场景下多个应用在涉及到反向解析别名冲突的时候无法正常解析。
解决方法1:名称空间
总路由添加名称空间。
path('app01/', include(('app01.urls', 'app01'), namespace='app01')),
path('app02/', include(('app02.urls', 'app02'), namespace='app02')),
应用反向解析自动提示
# app01应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after, name='after_view'),
]
# app01应用文件夹下views.py文件内
reverse('app01:after_view')
# app02应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after, name='after_view'),
]
# app02应用文件夹下views.py文件内
reverse('app02:after_view')
#html页面
{% url 'app01:after_view' %}
{% url 'app02:after_view' %}
解决方法2:别名不冲突即可
路由分发:总路由
path('app01/', include('app01.urls')),
path('app02/', include('app02.urls')),
子路由
# app01应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after, name='app01_after_view'),
] # 给别名加个前缀,保证别名不冲突
# app01应用文件夹下views.py文件内
reverse('app01_after_view')
# app02应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after, name='app02_after_view'),
]
# app02应用文件夹下views.py文件内
reverse('app02_after_view')
#html页面
{% url 'app01_after_view' %}
{% url 'app02_after_view' %}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了