Django路由层
当⽤户在您的Web应⽤程序上发出⻚⾯请求时,Django会获取url中请求路径(端 ⼝之后的部分),然后通过urls.py⽂件查找与路径相匹配的视图,然后返回HTML 响应或404未找到的错误(如果未找到)。在urls.py中,最重要的是 urlpatterns
列表。这是您定义URL和视图之间映射的地⽅。映射是URL模式中的path对象
1、路由匹配
from django.conf.urls import patterns, include
from app import views
urlpatterns = [
path('hello/', views.hello, name='hello'),
path('blog/', include('blog.urls')),
path对象有四个参数
-
模式串:匹配⽤户请求路径的字符串(和flask⼀样)
-
视图函数:匹配上⽤户指定请求路径后调⽤的是视图函数名 kwargs:
-
可选参数,需要额外传递的参数,是⼀个字典
-
名称(name):给路由命名,在代码中可以使⽤name进⾏反向解析(由 name获取⽤户请求路劲)。
另外,如果path中模式串如果不能满⾜你路由规则,还可以使⽤re_path对象, re_path对象中模式串是正则表达式,其他三个参数和path对象⼀致.
#路由匹配
re_path('test/',views.test),
re_path('testadd/',views.testadd)
"""
re_path第一个参数是正则表达式
只要第一个参数正则表达式能够匹配到内容,那么就会立刻停止往下匹配,直接执行对应的视图函数
在输入url会默认加斜杠,是应为django内部自动做了重定向
"""
在path中使⽤<参数名>表示所传参数,视图函数中的参数名必须和<>中参数名⼀ 致,参数可以是以下类型:
str:如果没有指定参数类型,默认是字符串类型。字符串参数可以匹配除/和
空字符外的其他字符串
int:匹配0和正整数,视图函数的参数将得到⼀个整型值
slug:匹配由数字、字⺟、-和_组成的字符串参数
path:匹配任何⾮空字符串,包括/。
- string
# 总路由
urlpatterns = [
path('admin/', admin.site.urls),
# 路由分发,根路由中包含子路由
# blog/ 路由前缀
path('blog/', include('App.urls')),
]
# 子路由
# string
path('change/<name>/', views.change, name='change'),
# path第三个参数name是路由的名字,与视图函数参数name无关
# views.py
def change(request, name):
return HttpResponse(name)
效果图:
- int
# 子路由
urlpatterns = [
# int
path('show/<int:age>/', views.show, name='show')
]
# views.py
def show(request, age):
print(type(age))
return HttpResponse(str(age))
效果图:
- slug
# 子路由
path('list/<slug:name>/', views.list, name='list')
# views.py
def list(request,name):
print(name,type(name))
return HttpResponse(name)
效果如图:
- path
# 子路由
# path,如果有多个参数,path类型必须在最后一个
path('access/<path:path>/',views.access,name='access')
# views.py
def access(request, path):
# path 可以包含任何字符,包括 /
return HttpResponse(path)
效果如图:
Django检查url模式之前会移除模式前的/
,所以url模式前⾯的/
可以不写,但如果 在地址栏⾥请求的时候不带尾斜杠,则会引起重定向,重定向到带尾斜杠的地址, 所以请求的时候要带尾斜杠。
django路由匹配 的时候其实可以匹配两次,第一次如果url后面没有加斜杠,django会让浏览器加斜杠在发送一次请求
# settings.py
APPEND_SLASH = False# 取消自动加斜杠,默认是True
"""取消了自动加斜杠后,再次访问浏览器就会报错"""
re_path
中模式包含了⼀ 个上尖括号(^
)和⼀个美元符号($
)。这些都是正则符号,上尖括号表示从字符串开 头匹配。美元符号表示匹配字符串的结尾,这两个符号和到⼀起就表示模式必须完 全匹配路径,⽽不是包含⼀部分。⽐如对于模式:
r'^hello/$'
如果不包含美元符,也就是r'^hello/'
,任何以/hello/的url都可以 匹配,例如:/hello/world/、/hello/1/2/等,同样如果不以上尖括号开头,则任何 以hello/做结尾的url都可以匹配。
# urls.py
from django.contrib import admin
from django.urls import path, re_path
from app03 import views
urlpatterns = [
#首页
re_path(r'^$',views.home),
#路由匹配
re_path(r'^test/$',views.test),
re_path(r'^testadd/$',views.testadd),
#尾页
# re_path(r'',views.error),
]
模式匹配的时候要注意:
- Django从上往下进⾏模式匹配,⼀旦匹配成功就不会往下继续匹配了 ⼀个视图函数可以有多个模式匹配
- 模式前⾯不需要加
/
- 如果匹配不上,则会引起异常,Django会调⽤错误处理视图处理(关闭调试模式)
2、无名/有名分组
在re_path中,()部分是正则的组, django在进⾏url匹配时,就会⾃动把匹配 成功的内容,作为参数传递给视图函数。
无名
- 无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数
"""
分组:就是给某一个正则表达式用小括号括起来
"""
#urls.py
re_path(r'^test/(\d+)',views.test),
#views.py
def test(request,xxx):
print(xxx)
return HttpResponse('test')
#
有名
- 有名分组就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数
"""
可以给正则表达式起别名
对正则表达式分组进⾏命名
"""
#urls.py
re_path(r'^testadd/(?P<year>\d+)', views.testadd),
#views.py
def testadd(request, year):
print(year)
return HttpResponse('testadd')
匹配/分组算法:
- 在⼀个匹配模式中要么使⽤命名分组,要么使⽤⽆命名分组,不能同时使⽤
- 请求的URL被看做是⼀个普通的Python 字符串, URLconf在其上查找并匹 配。进⾏匹配时将不包括GET或POST请求⽅式的参数以及域名。换句话讲, 对同⼀个URL的⽆论是POST请求、GET请求、或HEAD请求⽅法等等 —— 都 将路由到相同的函数。
- 每个捕获的参数都作为⼀个普通的Python 字符串传递给视图,⽆论正则表达 式使⽤的是什么匹配⽅式。
# 无名有名 不能混用
re_path(r'^demo/(\d+)/(?P<year>\d+)/',views.demo)
def demo(request, xx, year):
print(xx, year)
return HttpResponse('无名有名混用') 报错,结果报错
*************************************************************************************
# 单个分组可以使用多次
* 无名
re_path(r'^demo/(\d+)/(\d+)/',views.demo)
def demo(request, *args):
print(args)
return HttpResponse('demo')
* 有名
re_path(r'^demo/(?P<year>\d+)/(?P<month>\d+)/',views.demo)
def demo(request, *args,**kwargs):
print(kwargs)
return HttpResponse('demo')
3、反向解析
#通过一些方法得到一个结果,该结果可以直接访问对应的url触发视图函数
# 1.先给路由和视图函数起别名
re_path(r'^func/',views.func,name='zs'),
# 2.反向解析
#后端反向解析
from django.shortcuts import reverse
def home(request):
print(reverse('zs'))
return render(request,'home.html')
#前端反向解析
<a href="{% url 'zs' %}">111</a>
"""别名不能出现冲突!!!"""
4、无名有名反向解析
#无名分组的反向解析
re_path(r'^index/(\d+)/',views.index,name='zs'),
#前端
<a href="{% url 'zs' 1 %}"></a>
#后端
from django.shortcuts import reverse
def home(request):
print(reverse('zs',args=(1,))) #/index/1/
return render(request,'home.html')
"""
数字 一般放的是数据的主键值, 来做数据的编辑和删除
"""
# 有名分组反向解析
re_path(r'^func/(?P<year>\d+)/',views.func,name='li'),
#前端
<a href="{% url 'li' year=123 %}"></a>
#简单写法
<a href="{% url 'li' 123 %}"></a>
#后端
def home(request):
print(reverse('li',kwargs={'year':123}))
#简单写法
# print(reverse('li', args=(123,)))
return render(request, 'home.html')
5、路由分发
"""
Django的每一个应用都可以有自己的templates文件夹,urls.py static文件夹
正是基于上述的特点,Django能够非常好的做到多人分组开发,(每个人只写自己的app)
当一个django项目中的url特别多,总路由urls.py代码就非常冗余,不易于维护,
这个时候就可以利用路由分发,减轻总路由压力
利用路由分发之后,总路由不再干路由与视图函数的直接对应关系
而是做一个分发处理
识别当前url属于哪个应用下的,直接分发给对应的应用去处理
"""
"""总路由"""
from app01 import urls as app01_urls
from app02 import urls as app02_urls
from django.urls import path, re_path, include
urlpatterns = [
# 1.第一种方式 路由分发
#re_path(r'^app01/', include(app01_urls)), # 只要re_path前缀是app01开头的,全部交给app01处理
#re_path(r'^app02/', include(app02_urls)), # 只要re_path前缀是app02开头的,全部交给app02处理
# 2.第二宗方式 路由分发,不用导模块,
re_path(r'^app01/',include('app01.urls')),
re_path(r'^app02/',include('app02.urls'))
#总路由里面的re_path不能加$结尾
]
"""子路由"""
#app01下urls.py
from django.urls import path, re_path
from app01 import views
urlpatterns = [
re_path(r'^register/',views.register)
]
#app02下urls.py
from django.urls import path, re_path
from app02 import views
urlpatterns = [
re_path(r'^register/',views.register)
]
6、名称空间
# 当多个应用出现了相同的别名,反向解析不能自动识别应用前缀
#名称空间
#总路由
path('app01/', include('app01.urls', namespace='app01')),
path('app02/', include('app02.urls', namespace='app02'))
#解析的时候
#后端
#app01下的urls.py
urlpatterns = [re_path(r'^register/',views.register,name='reg')]
#app02下的urls.py
urlpatterns = [re_path(r'^register/',views.register,name='reg')]
#前端
{% url 'app01:reg' %}
{% url 'app02:reg' %}
#只要保证名字不冲突,就没有必要使用名称空间
"""
一般情况下,有多个app的时候,在起别名时会加上app的前缀
这样就能确保多个app之间名字不冲突
"""
#加前缀
urlpatterns = [
re_path(r'^register/',views.register,name='app02_reg')
]
urlpatterns = [
re_path(r'^register/',views.register,name='app01_reg')
]
7、伪静态
"""
将一个动态网页为伪装成静态网页
伪装的目的在于增大网站的 seo查询力度
并且增加搜友引擎收藏本网站的概率
搜索引擎本质上就是一个巨大的爬虫引擎
"""
本文来自博客园,作者:ExpiredSaury,转载请注明原文链接:https://www.cnblogs.com/saury/p/16976255.html