路由系统是把接收到的请求,根据网址进行匹配,指定处理请求的函数或类。
网站框架路由系统一般分为两类,FBV,CBV,Django两者都支持,但有的框架只支持一种。
两个功能,一个是直接转到函数,一个是转到下级urls.py路由
urlpatterns=[
path(r'blog/', blog.views.index),
path(r'bbs/', bbs.views.index)
path(r'pathreg/',include('app.urls'))
#include('APP名.APP路由文件')
]
Django 1.XX使用url函数,可以使用正则,可以使用固定字符串
Django 2.XX以后使用path和re_path,
from django.conf.urls import url # django 1.XX使用 url
from django.conf.urls import url, re_path # django 2.XX 使用 url和re_path
from django.urls import path, re_path # django 2.1X 以后集成,使用 path和re_path
url()函数传递了四个参数,两个必需:regex和view,以及两个可选:kwargs,和name。也就是正则表达式和视图是两个必填参数。
完成指定字符串或格式的匹配,函数 path() 具有四个参数,两个必须参数:route 和 view,两个可选参数:kwargs 和 name。即路由和视图是必填参数
正则匹配,path完成不了的匹配
--后集成位置django.urls
格式:path(匹配规则, views视图函数或类方法, **kwargs, name)
匹配规则:不支持正则,但自身提供了五种匹配模式
int 匹配0和正整数,如 1230
str 匹配任何非空字符串但不包括/,
slug 匹配字母、数字以及横杠、下划线组成的字符串。
uuid 匹配一个uuid对象,如 075194d3-6885-417e-a8a8-6c931e272f00。(该对象必须包括破折号—,所有字母必须小写)
path 匹配所有的字符串 包括/(意思就是path前边和后边的所有)
app的views.py的方法,或类方法
向views传递的参数
后端反向解析,前端根据 name值找到解析路由
一般分为三种情况:
from django.urls import path, re_path
import index.views
import pathtest.views
urlpatterns = [
path(r'pathtest/', pathtest.views.index),
# r'pathtest/'严格匹配,前端使用pathtest/ 1 2 3传参是会报错。
# The current path, pathtest/ 1 2 3, didn't match any of these.
path(r'pathtest ' , pathtest.views.index),
# 使用<>从url中捕获值,pathtest/ 1,pathtest.views.index函数必须接收参数,否则报错,可以是实参,也可以是kwargs
# index() got an unexpected keyword argument 'id_1'
path(r'pathtest ' , pathtest.views.index),
# 匹配str型的参数,并命名为book_id,传给views.index函数
# str,int, slug, uuid, path,五种默认的匹配模式
]
指定本条规则,处理请求的views.py的函数(FBV)或类(CBV):
FBV:urls.py处理请求后,把请求交给函数index,index处理后,返回pathtest.html页面给客户端。
from django.urls import path, re_path
import index.views
urlpatterns = [
path(r'pathtest ' , pathtest.views.index),
# str,int, slug, uuid, path,五种默认的匹配模式
]
from django.shortcuts import render
def index(request,*args,**kwargs):
para = []
if kwargs:
for k,v in kwargs.items():
print(k,':',v)
if args:
for i in args:
print(i)
return render(request, 'pathtest.html', {'para': para})
CBV: 1、Class需要继承django.views.generic 的View类 2、URLS.py路由转发到 APP.views.类.as_view() 3、as_view()是继承View类,不需要自己重写 4、查看generic\base.py 的as_view方法,看到是通过hasattr进行判断用户请求方式,通过dispach 执行相对应的请求方法函数 5、可以通过向 http_method_names注册 新的方法实现自定义
http://127.0.0.1:8000/pathtest1/ 显示CBV1
http://127.0.0.1:8000/pathtest2/ 显示CBV2
from django.urls import path, re_path
import pathtest.views
urlpatterns = [
path(r'pathtest1/', pathtest.views.CBV1.as_view()),
path(r'pathtest2/', pathtest.views.CBV2.as_view())
]
APP:pathtest Views.py
from django.view.generic import
class CBV1(View):
def get(self,request,*args,**kwargs):
return HttpResponse('CBV1
')
class CBV2(View):
def get(self,request,*args,**kwargs):
return HttpResponse('CBV2
')
可以向views传递字典型参数,views函数可以使用实参或形参接收,使用形参接收时,通过path函数传递的参数始终在url网址传递的参数前。
urlpatterns = [path(r'pathtest1/' , pathtest.views.CBV1.as_view(),{'since':'O-K'})]
# 向views.py传递{'since':'O-K'}
class CBV1(View):
def get(self,request, *args, **kwargs):
# 使用实参接收def get(self,request, since, *args, **kwargs):
para = []
if kwargs:
for k,v in kwargs.items():
print(k,':',v)
para.append(v)
return HttpResponse('CBV2{}
'.format(para))
# 访问:http://127.0.0.1:8000/pathtest1/0010
# 网页显示:CBV2['O-K', 10]
{%url 'name值引用'%}
,url代指当前网址。views渲染HTML模板{%url 'name值' %}
时,根据name值找到urls.py中对应的path路由,把path匹配规则字符串替换到 HTML模板的‘name值’
urlpatterns = [
path(r'pathtest1/', pathtest.views.CBV1.as_view()), # 定义正向路由http://127.0.0.1:8000/pathtest1/访问CBV1
path(r'pathtest2/' , pathtest.views.CBV2.as_view(), name='patht') # 使用name定义反向
# path(r'lllllllllll/', pathtest.views.CBV2.as_view(), name='patht') # 使用name定义反向,匹配规则改变不影响name
]
form django.shorsturc import HttpResponse, reverse
class CBV2(View):
def get(self,request,page_num, *args, **kwargs):
route_path=reverse('patht', args=(page_num,))
# reverse,转换成际的URL地址,patht是urls里的name值,转换成匹配值
# args:地址里的参数个数,几个就写几个,比如四个(page_num1,page_num2,page_num3,page_num4)
print(route_path) # 打印出来
return HttpResponse('CBV2:
page_num:{}
'.format(page_num)) #根据点击的链接不同,获取的返回值也不同
class CBV1(View):
def get(self,request, *args,**kwargs):
return render(request, 'pathtest.html')
<body>
\\使用patht的name名来定义网址路由,后面的123是获取值,所以,三个链接都会执行views的CBV2
<a href="{% url 'patht' 100 %}">num</a>
<a href="{% url 'patht' 200 %}">numb/a>
<a href="{% url 'patht' 300 %}">numbe</a>
</body>
访问:http://127.0.0.1:8000/pathtest1/,点击html里的任何链接都会执行CBV2,因为定义了name值。
点击任意一个链接,views的route_path:/pathtest2/100
path里默认有四个匹配规则,int,str,slug,uuid,path,
也可以自定义匹配规则,步骤:定义类;使用register_converter 注册;使用。
from django.urls import path, register_reverter
import pathtest.views
class NumLine:
# 第一步,定义类
regex='[-0-9]+'
def to_python(self, value):
return str(value) //可以进行类型的转换和处理,再返回
def to_url(self, value):
return str(value) //可以进行类型的转换和处理,再返回
# 第二步,向转换器里注册自定义类,并起个名numline
register_reverter(NumLine,'numline')
urlpatterns=[
path(r'pathtest1/', pathtest.views.CBV1.as_view()),
path(r'ppppppppp/ ' ,pathtest.views.CVB2.as_view(),name='patht')
# 使用自义定的numline,匹配参数
]
from django.shortcuts import HttpResponse, render, reverse
from django.views.generic import View
class CBV1(View):
def get(self,request):
return render(request,'pathtest.html')
class CBV2(View):
def get(self,request,data1, data2):
full_path = reverse('patht',args=(data1,data2))
return HttpResponse('Full path:{}
CBV2:
page_num:{},{}
'.format(full_path, data1, data2))
<a href="{% url 'patht' '-0--' 1111 %}">number</a> //字符型参数传入时,一定要加引号
<a href="{% url 'patht' -2344 2222 %}">number</a> //这里的-不报错,因为识别成了负数
<a href="{% url 'patht' 3323 3333 %}">number</a>
访问时,只识别传入的-和0-9,其它参数报错。
使用include方法进行指定,include从django.urls导入
格式:path(r’pathreg/’,include(‘app.urls’)) ,include(‘APP名.APP路由文件’)
from django.urls import path, include
urlparrents=[
path(r'pathreg/',include('pathtest.urls')),
]
from django.urls import path, include
from pathtest import views
urlparrents=[
path(r'',views.CBV1.as_view()),
path(r'index/',views.CBV2.as_view()),
]
from django.shortcuts import HttpResponse
from django.views.generic import View
class CBV2(View):
def get(self,request):
return HttpResponse('index page
')
class CBV1(View):
def get(self, request):
return HttpResponse('default page'
)
http://127.0.0.1:8000/pathreg/,经过project的urls路由文件匹配pathreg,分发到app的urls路由文件,调用CBV1显示default page
http://127.0.0.1:8000/pathreg/index,经过project的urls路由文件匹配pathreg,分发到app的urls路由文件匹配index,调用CBV1显示index page
与Django1.xx版本的url功能一样
path(r'', views.CBV1.as_view()),
re_path(r'index$', views.CBV2.as_view()),
# http://127.0.0.1:8000/pathtest/1111111111111index
re_path(r'^index', views.CBV2.as_view()),
# http://127.0.0.1:8000/pathtest/index1111111111111
re_path(r'index', views.CBV2.as_view()),
# 这才是重点,只要包含连续的index,都会找到DBV2
re_path(r'^[a-zA-Z][_0-9a-zA-Z]{5,9}$', views.CBV2.as_view())
# 匹配以字母开头,后面由数字或下划线或字母组成的最短是6,最长是10个字符的路径
# 注意:{5,9}匹配6,10个字符,因为开头那个不算在{5,9}选项里
# http://127.0.0.1:8000/pathtest/i_d111ex11 匹配
re_path(r'^test/(?P\d+)$' , views.CBV2.as_view())
# 使用()获取url的值
# (?Pvalue)、给获取的值,赋给name的变量,在views函数中使用def test(request,name)或def test(request,**kwargs)
找到 django.views.generic .View类,
默认提供了http_method_names列表里的方法,
as_view函数进行了一些参数等判断,
最后返回了dispach方法,
dispach通过反射(getattr)执行相应的函数
增加自定义提示方法:
通过重写dispach方法,给所有方法增加因定操作
def dispatch(self, request, *args, **kwargs):
print('操作前的操作')
obj = super(Cbv,self).dispatch(request, *args, **kwargs)
print('操作后的操作代码')
return obj
namespace,app_name,name
在project的urls配置namespace(实例命名空间),同时要在跳转APP的urls配置 app_name(应用命名空间)
主要是实现以APP名区分的路由转发。
# urls.py:
path('/a/', include('test.urls', namespace='author')) # namespace **必须
# test/urls.py:
app_name='dync_name' # app_name,根据urls的namespace改变。 **必须在url里注册,如果与namespace一样默认指向namespace
re_path(r'^test/(?P\d+)/$' , views.repath, name='detail') # **name必须
path(r'test/' , views.path, name='app01'),
# views中使用 reverse生成url,reverse('author:index'),-->/a/index/
# 带参数的:
reverse('author:detail', kwargs={'id':666}) # kwargs里面的key似乎不是很重要,可以变成其它名
reverse('author:app01', args=[sid])
# 模板带参的:
{%url 'app_name:detail' id=666 %}