今日学习目标
- 对Django框架生命周期有了解,详细学习其中的路由层知识
前言
-
django请求生命周期流程图
-
路由层相关知识
一、django请求生命周期流程图
后期对Django的学习都是按照上面各个单个处理层来详细了解。
二、路由层相关知识
路由层样式,今天就是围绕这个
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
来讲解其中的相关知识
路由匹配
url(r'^admin/', admin.site.urls),
这段代码就是用来将前端发来的请求(URL)的后缀与后端的视图函数进行映射匹配,从而完成前后端联动。
路由匹配的特点:
1.只要匹配上了就会立刻结束执行对应的视图函数
2.url方法的第一个参数其实是一个正则表达式
只要正则表达式能够从用户输入的后缀中匹配到内容就算匹配上了
思考分析:
正因为其中有正则表达式这种特点的存在,导致整个URL出现了相应的不严谨。
eg:
正则是test时,URL后缀内容是test ,那么可以匹配出text的视图
正则是test时,URL后缀内容是test123 ,那么也可以匹配出text的视图
改进一:
前面已经明确指出问题产生的主要原因是正则的问题,那么就利用正则去规范一下URL
正则是test/ 内容是test 那么首次无法匹配
# django二次追加斜杠机制
首次匹配不上 那么django还会让浏览器默认加斜杠再次发送请求
test 301
test/ 200
'''
了解:斜杠机制可以取消 但是不推荐
APPEND_SLASH = False
'''
改进二:
当正则是test/ 内容是abcdefgtest/ 那么可以匹配出文本test/
可以在正则的最前面加上上箭头来限制,解决路由前面可以随意乱写的问题
改进三:
正则是^test/ 内容是test/abc/edf/acd/ 那么可以匹配出文本test/
可以在正则的最后面加上$来限制,解决路由后面可以随意乱写的问题
小总结:
由于第一个参数是正则 所以当项目特别大 对应关系特别多的时候要格外的注意是否会出现路由顶替的现象
小扩展:
可以定制一个主页面 用户不携带后缀可以直接访问(掌握)
url(r'^$',views.home)
也可以定义一个尾页 用户输入一个没有对应关系的直接返回(了解)
url(r'.*',views.error)
无名分组
前面提到了路由匹配的问题,主要原因就是前面的正则表达式引起的,这时以我们对正则表达式的了解,好像它还可以进行分组处理。这就可以将上面的代码改写一下:
url(r'^text/([0-9]{4})/$', views.text)
结果:
路由匹配成功之后就会调用视图函数默认情况下会自动给视图函数传递一个request位置参数
def text(request):
如果路由匹配中使用括号对正则表达式进行了分组 那么在调用视图函数的时候,会将括号内匹配到的内容当做位置参数传递给视图函数
def test(request,括号内正则表达式匹配到的内容):
小总结:
上述特性django称之为’无名分组’
有名分组
同样的在正则表达式了除了可以分组,还可以给每个组进行命名
url(r'^text/(?P<user_id>[0-9]{4})$', views.text)
结果
给括号内的正则表达式起别名之后 匹配成功则会讲括号内匹配到的内容按照关键字参数传递给视图函数
def text(request,user_id=括号内正则表达式匹配到的内容)
小总结:
上述特性django称之为’有名分组’
两者是否可以混合使用
url(r'^test/(\d+)/(?P<user_id>[0-9]{4})/$', views.testadd) # 不可以
无名有名分组不能混合使用,单个可以重复使用
url(r'^test/(\d+)/(\d+)/$', views.testadd) # 可以
url(r'^test/(?P<a>\d+)/(?P<b>\d+)',views.testadd) # 可以
总结:
1.其实无名分组就是给视图函数添加了一个位置形参
2.其实有名分组就是给视图函数添加了一个关键字形参
3.这个在URL里多出来的值,一般情况下这个值可以是数据的主键值、页面的页码、区域的编号等
反向解析
引言:
之前在介绍Django框架时有提到静动态文件的事,既然那里面可以对一些变量值进行动态配置,那么这个路由匹配为什么不能呢,在路由层就是利用反向解析来进行处理的。
反向解析
通过反向解析可以获取到一个结果 该结果可以访问到一个路由
步骤1:给对应关系起别名
url(r'^func666/',views.func,name='func_view')
步骤2:使用反向解析获取结果
前端:
{% url 'func_view' %} # func666/ 结果可以访问路由
后端:
from django.shortcuts import reverse
reverse('func_view') # func666/ 结果可以访问路由
无名分组反向解析
步骤1:给对应关系起别名
url(r'^func666/(\d+)/',views.func,name='func_view')
步骤2:使用反向解析获取结果
‘’‘无法明确括号内正则表达式的内容 需要人为指定’‘’
前端:
{% url 'func_view' 123 %} # func666/123/
后端:
from django.shortcuts import reverse
reverse('func_view',args=(666,)) # func666/666/
有名分组反向解析
步骤1:给对应关系起别名
url(r'^func666/(?P<id>\d+)/',views.func,name='func_view')
步骤2:使用反向解析获取结果
'''无法明确括号内正则表达式的内容 需要人为指定'''
前端:
{% url 'func_view' 123 %} # func666/123/
{% url 'func_view' id=123 %} # func666/123/
后端:
from django.shortcuts import reverse
reverse('func_view',args=(666,)) # func666/666/
reverse('func_view',kwargs={'id':1}) # func666/1/
路由分发
问题引入:
如果一个django项目特别庞大 里面有很多应用 每个应用下有很多对应关系,那么django自带的路由层里面的代码就会非常非常的多 如何优化???
解决方式:
根据应用的不同拆分到不同的应用中
django支持每个应用都可以有自己独立的
路由层、模板层、静态文件、视图层(默认)、模型层(默认)
路由分发优点:
上述特性能够让django在分组开发上更加的方便、快捷
所有人都可以在应用中开发完整的项目功能,最后汇总到一个空的django项目中 然后通过路由分发整合所有人的应用
就是去让项目处理进行解耦合
具体步骤:
1.创建多个应用 并去配置文件中注册
INSTALLED_APPS = [
'app01',
'app02'
]
2.在多个应用中编写相同的路由(创建各自的urls.py)
urlpatterns = [
url(r'^index/',views.index111)
]
urlpatterns = [
url(r'^index/',views.index)
]
3.路由分发
总路由
from django.conf.urls import url, include
from app01 import urls as app01_urls
from app02 import urls as app02_urls
url(r'^app01/',include(app01_urls)),
url(r'^app02/',include(app02_urls))
"""总路由只负责分发 不负责视图函数对应"""
上述代码还可以简写
from django.conf.urls import url, include
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))
名称空间
既然将各自的路由分开管理了,那么就会造成下面的问题:
1.不同的应用使用了相同的别名 那么反向解析是不会自动识别
index_view app01/index/
index_view app02/index/
解决方式:
方式1:名称空间
总路由添加名称空间
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))
应用反向解析自动提示
reverse('app01:index_view')
reverse('app02:index_view')
{% url 'app01:index_view' %}
{% url 'app02:index_view' %}
方式2:只需要确保反向解析的别名在整个项目中不重复即可!!!
可以在别名的前面加上应用名的前缀
url(r'^index/',views.index,name='app01_index_view')
url(r'^index/',views.index,name='app02_index_view')
补充:
名称空间其实是可有可无的知识 但是在实际工作中还是有不少程序员喜欢使用
案例提升
需求:
使用无名有名反向解析完成用户数据的编辑和删除功能
提示:用户数据使用表格标签展示 然后每一行放编辑和删除按钮
点击编辑按钮进入编辑页面 修改数据
点击删除按钮 直接删除数据并刷新页面
views.py
from app01 import models
from django.shortcuts import render, redirect
# Create your views here.
def user_list(request):
u_list = models.Userinfo.objects.all()
return render(request, 'user_list.html', locals())
def update_user(request, u_id):
update_id = u_id
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
models.Userinfo.objects.filter(id=update_id).update(username=username, password=password)
return redirect('/user_list/')
return render(request, 'update_user.html')
def delete_user(request, u_id):
delete_id = u_id
models.Userinfo.objects.filter(id=delete_id).delete()
return redirect('/user_list/')
urls.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^user_list/', views.user_list),
url(r'^update_user/(?P<u_id>\d+)/', views.update_user, name='update_user'),
url(r'^delete_user/(?P<u_id>\d+)/', views.delete_user, name='delete_user'),
]