栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

请简述Django的URL路由流程_django子路由?

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

请简述Django的URL路由流程_django子路由?

DjangoURL调度器 – 潘登同学的后端笔记

文章目录

DjangoURL调度器 -- 潘登同学的后端笔记 工作原理

请求参数自定义路径转换器直接写正则路径re_path() 错误处理引入其他路由

URL反向解析

在Python代码中在模板中 命名空间

在Python代码中在模板中在Python代码中在模板中

工作原理

​django通过urlconf来映射视图函数,只区分路径,不区分http方法

Django确定要使用的根URLconf模块,一般是在settings中的ROOT_URLCONF设置的值,但是如果传入 HttpRequest 对象具有一个 urlconf 属性(由中间件设置),则其值将用于代替 ROOT_URLCONF 设置。Django加载该URLconf模块并查找变量 urlpatterns,它是一个列表django.urls.path() 和 / 或django.urls.re_path()实例。Django按顺序遍历每个URL模式,并停在与请求的URL匹配的第一个URL模式,需要特别注意编写的顺序一旦某个URL模式匹配,Django就会导入并调用给定的视图,该视图是一个简单的Python函数(或基于类的视图方法)。该视图通过以下参数传递:

一个HttpRequest实例。如果匹配的URL模式没有返回任何命名组,则来自正则表达式的匹配作为位置参数提供。关键字参数由路径表达式匹配的任何命名部分组成,并由可选的kwargs参数传给 django.urls.path()或django.urls.re_path()。 如果没有URL模式匹配,或者在此过程中的任何点发生异常,Django将调用适当的错误处理视图 请求参数

str:匹配任何非空字符串,不包括路径分隔符’/’。如果转换器不包含在表达式中,这是默认值。int:匹配零或任何正整数。返回一个int。slug:匹配由ASCII字母或数字组成的字符串,以及横线和下划线字符。例如, building-your-1st-django_site可以匹配,django_@site是不可以匹配的。uuid:匹配格式化的UUID。为防止多个URL映射到同一页面,必须包含破折号,并且字母必须是小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID实例。path:匹配任何非空字符串,包括路径分隔符 ‘/’,可以匹配完整的URL路径,而不仅仅是URL路径的一部分str,使用时要谨慎,因为可能造成后续的所有url匹配都失效。

主应用下的urls.py

from django.urls import path
from myapp01 import views
urlpatterns = [
    path('my_request/', views.my_request),
    path('login/',views.first_html),
    path('articles/2003/', views.special_case_2003),
    path('articles//', views.year_archive),
    path('articles///', views.month_archive),
    path('articles////', views.article_detail),
    path('articles//', views.str_archive),
    path('articles//', views.path_archive),
]

注意

传参的时候,形参的名称要与urls的一致没有必要添加一个前导斜杠,因为每个URL都有,例如,使用articles而不是/articles

def special_case_2003(request):
    return HttpResponse('articles,year:2003')

def year_archive(request,year):
    return HttpResponse(f'articles,year:{year}')

def month_archive(request,year,month):
    return HttpResponse(f'articles,year:{year},month:{month}')

def article_detail(request,year,month,slug):
    return HttpResponse(f'articles,year:{year},month:{month},you say:{slug}')

def str_archive(request,string):
    return HttpResponse(f'articles,name:{string}')
自定义路径转换器

转换器是一个包含以下内容的类:

一个regex类属性,作为一个re匹配字符串。to_python(self, value)方法,它处理匹配的字符串转换成要传递到视图函数的类型。to_url(self, value)方法,用于处理将Python类型转换为URL中使用的字符串。

在子应用下创建converters.py文件,创建一个类,想实现姓名首字母加学号

class NameAndStudentID(object):
    regex = '[a-z]{2,3}[0-9]{10}'

    def to_python(self,value):
        return str(value)
    
    def to_url(self,value):
        return value

在子应用的urls.py处注册自定义转化器类

from myapp01 import views,converters
register_converter(converters.NameAndStudentID, 'nameid')

urlpatterns = [
    path('query//',views.querynameandID),  # nameid与上面的对上
]

再回到views.py中写视图函数

def querynameandID(request,arg):
    regex1 = re.compile(r'[a-z]{2,3}')
    regex2 = re.compile(r'[0-9]{10}')
    name = regex1.findall(arg)[0]
    id = regex2.findall(arg)[0]
    return HttpResponse(f'Hello {name}! Your Student ID is: {id}')
直接写正则路径re_path()

直接在urlpatterns中写

from django.urls import re_path
urlpatterns = {
    re_path(r'^query/(?P[a-z]{2,3}[0-9]{10})/$', views.querynameandID),
    # 可以不写?P,直接写正则,但是这样传参的时候不方便,会将变量弄混,不推荐
}

其中也可以参数嵌套

from django.urls import re_path
urlpatterns = {
    re_path(r'^query/pd-(?P[0-9]{10})/$', views.queryID),
    # 可以不写?P,直接写正则,但是这样传参的时候不方便,会将变量弄混,不推荐
}
def queryID(request,ID):
    return HttpResponse(f'Hello PD! Your Student ID is: {ID}')
错误处理

handler400- 状态码400handler403- 状态码403handler404- 状态码404handler500- 状态码500

    在 settings 中修改配置:
DEBUG = False

ALLOWED_HOSTS = ['*', ]
    在主应用的urls中配置:
# myapp01是子应用
handler404 = "myapp01.views.page_not_found"
    在myapp01应用的views中添加函数page_not_found:
def page_not_found(request, exception):
    html = '''


	
		
		Fargo 404
		
		
			html,
			body {
			  height: 100%;
			  min-height: 450px;
			  font-family: "Dosis", sans-serif;
			  font-size: 32px;
			  font-weight: 500;
			  color: #5d7399;
			}
			
			.content {
			  height: 100%;
			  position: relative;
			  z-index: 1;
			  background-color: #d2e1ec;
			  background-image: linear-gradient(to bottom, #bbcfe1 0%, #e8f2f6 80%);
			  overflow: hidden;
			}
			
			.snow {
			  position: absolute;
			  top: 0;
			  left: 0;
			  pointer-events: none;
			  z-index: 20;
			}
			
			.main-text {
			  padding: 20vh 20px 0 20px;
			  text-align: center;
			  line-height: 2em;
			  font-size: 5vh;
			}
			
			.home-link {
			  font-size: 0.6em;
			  font-weight: 400;
			  color: inherit;
			  text-decoration: none;
			  opacity: 0.6;
			  border-bottom: 1px dashed rgba(93, 115, 153, 0.5);
			}
			.home-link:hover {
			  opacity: 1;
			}
			
			.ground {
			  height: 160px;
			  width: 100%;
			  position: absolute;
			  bottom: 0;
			  left: 0;
			  background: #f6f9fa;
			  box-shadow: 0 0 10px 10px #f6f9fa;
			}
			.ground:before, .ground:after {
			  content: "";
			  display: block;
			  width: 250px;
			  height: 250px;
			  position: absolute;
			  top: -62.5px;
			  z-index: -1;
			  background: transparent;
			  transform: scaleX(0.2) rotate(45deg);
			}
			.ground:after {
			  left: 50%;
			  margin-left: -166.6666666667px;
			  box-shadow: -340px 260px 15px #bac4d5, -625px 575px 15px #91a1bc, -855px 945px 15px #7e90b0, -1165px 1235px 15px #b0bccf, -1470px 1530px 15px #94a3be, -1750px 1850px 15px #91a1bc, -2145px 2055px 15px #b0bccf, -2400px 2400px 15px #7e90b0, -2665px 2735px 15px #a7b4c9, -2965px 3035px 15px #8496b4, -3260px 3340px 15px #94a3be, -3580px 3620px 15px #97a6c0, -3885px 3915px 15px #9aa9c2, -4160px 4240px 15px #8193b2, -4470px 4530px 15px #8e9eba, -4845px 4755px 15px #7e90b0;
			}
			.ground:before {
			  right: 50%;
			  margin-right: -166.6666666667px;
			  box-shadow: 260px -340px 15px #b0bccf, 630px -570px 15px #a1aec6, 925px -875px 15px #94a3be, 1170px -1230px 15px #a7b4c9, 1535px -1465px 15px #a7b4c9, 1845px -1755px 15px #8a9bb8, 2150px -2050px 15px #b7c1d3, 2445px -2355px 15px #8798b6, 2735px -2665px 15px #bac4d5, 3015px -2985px 15px #94a3be, 3270px -3330px 15px #b7c1d3, 3620px -3580px 15px #8193b2, 3860px -3940px 15px #9dabc4, 4215px -4185px 15px #8798b6, 4485px -4515px 15px #8e9eba, 4810px -4790px 15px #bac4d5;
			}
			
			.mound {
			  margin-top: -80px;
			  font-weight: 800;
			  font-size: 180px;
			  text-align: center;
			  color: #dd4040;
			  pointer-events: none;
			}
			.mound:before {
			  content: "";
			  display: block;
			  width: 600px;
			  height: 200px;
			  position: absolute;
			  left: 50%;
			  margin-left: -300px;
			  top: 50px;
			  z-index: 1;
			  border-radius: 100%;
			  background-color: #e8f2f6;
			  background-image: linear-gradient(to bottom, #dee8f1, #f6f9fa 60px);
			}
			.mound:after {
			  content: "";
			  display: block;
			  width: 28px;
			  height: 6px;
			  position: absolute;
			  left: 50%;
			  margin-left: -150px;
			  top: 68px;
			  z-index: 2;
			  background: #dd4040;
			  border-radius: 100%;
			  transform: rotate(-15deg);
			  box-shadow: -56px 12px 0 1px #dd4040, -126px 6px 0 2px #dd4040, -196px 24px 0 3px #dd4040;
			}
			
			.mound_text {
			  transform: rotate(6deg);
			}
			
			.mound_spade {
			  display: block;
			  width: 35px;
			  height: 30px;
			  position: absolute;
			  right: 50%;
			  top: 42%;
			  margin-right: -250px;
			  z-index: 0;
			  transform: rotate(35deg);
			  background: #dd4040;
			}
			.mound_spade:before, .mound_spade:after {
			  content: "";
			  display: block;
			  position: absolute;
			}
			.mound_spade:before {
			  width: 40%;
			  height: 30px;
			  bottom: 98%;
			  left: 50%;
			  margin-left: -20%;
			  background: #dd4040;
			}
			.mound_spade:after {
			  width: 100%;
			  height: 30px;
			  top: -55px;
			  left: 0%;
			  box-sizing: border-box;
			  border: 10px solid #dd4040;
			  border-radius: 4px 4px 20px 20px;
			}
		
	
		
		
		  
		  
		    Aw jeez.
That page has gone missing.Hitch a ride back home. 404 ''' return HttpResponse(html)
引入其他路由
    如果路由太多的话,不方便管理,将同类型的路由写在一起
from django.urls import include, path
date_patterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles//', views.year_archive),
    path('articles///', views.month_archive),
    path('articles////', views.article_detail),
]
urlpatterns = [
    # path('query//',views.querynameandID),
    re_path(r'^query/pd-(?P[0-9]{10})/$', views.queryID),
    re_path(r'^query/(?P[a-z]{2,3}[0-9]{10})/$', views.querynameandID),
    path('my_request/', views.my_request),
    path('login/',views.first_html),
    path('articles//', views.article_uuid),
    path('articles//', views.str_archive),
    path('articles//', views.path_archive),
    path('',include(date_patterns))
]
    如果路由用同样的前缀,可以共用一个,把不同的放到include中
urlpatterns = [
    # path('query//',views.querynameandID),
    re_path(r'^query/pd-(?P[0-9]{10})/$', views.queryID),
    re_path(r'^query/(?P[a-z]{2,3}[0-9]{10})/$', views.querynameandID),
    path('my_request/', views.my_request),
    path('login/',views.first_html),
    path('articles/',include([
        path('articles//', views.article_uuid),
        path('articles//', views.str_archive),
        path('articles//', views.path_archive),
        ]))
    path('',include(date_patterns))
]
    传递捕获的参数

在主urls中配置:

urlpatterns = [
    path('admin/', admin.site.urls),
    # path('myapp01/', include('myapp01.urls')),
    path('/myapp01/',include('myapp01.urls'))
]

在子应用的urls.py下设置

urlpatterns = [
    path('test_username/',views.test)
]

在视图函数中

def test(request,username):
    return HttpResponse(f'username:{username}')
URL反向解析

url调度器除了从用户发起请求,到匹配对应的view,还能在python程序中调用进行匹配,通过 path或re_path 中 的name属性进行解析

在模板中,使用url模板标签在Python代码中(主要是views),使用 reverse() 函数在模型实例中,使用 get_absolute_url() 方法 在Python代码中

在子应用需要被重定向的路由中,给上name属性

在reverseappurls.py下

from django.urls import path
from reverseapp import views
urlpatterns = [
    path('first_request_url/',views.first_request),
    path('articles//',views.articles_year,name='articles-year-redirect'),
]

在reverseappviews.py下

from django.urls import reverse
from django.http import HttpResponse, HttpResponseRedirect

def first_request(request):
    # return HttpResponse('first-request')
	# 这里的reverse中的参数应与上面的name保持一致
    return HttpResponseRedirect(reverse('articles-year-redirect',args=(2020,)))

def articles_year(request,year):
    return HttpResponse(f'articles,year:{year}')

最后记得在主应用setting下挂载子应用,在主应用urls下也挂载子应用,访问http://127.0.0.1:8000/reverseapp/first_request_url/ 就会跳转到 http://127.0.0.1:8000/reverseapp/articles/2020/

urlpatterns = [
    path('reverseapp/',include('reverseapp.urls')),
]
在模板中

在子应用下创建模板reverseapptemplatesredirect.html




    
    
    
    Redirect


    2020 Article


将需要重定向的路由在reverseappurls.py中注册

urlpatterns = [
	path('do__html',views.do_html),
]

在reverseappviews.py下,

def do_html(request):
    return render('redirect.html')

访问http://127.0.0.1:8000/reverseapp/do__html/ 就会跳转到 http://127.0.0.1:8000/reverseapp/articles/2020/

命名空间

主要用于配合 url 反向解析使用,多个不同的urls(子应用)文件中可能配置同名的 name,那么为了进行区分,给不同的urls进行不同的命名,切记同一个项目下命名空间不能重复!

​ 通过在 url调度器的模块中,定义 app_name = ‘reverseapp’ 来命名

在reverseappurls.py下

app_name = 'reverse'  # 只要加一个这个即可
urlpatterns = [
    path('first_request_url/',views.first_request),
    path('articles//',views.articles_year,name='articles-year-redirect'),
]
在Python代码中

在reverseappviews.py下,

def first_request(request):
    # return HttpResponse('first-request')
	# 在name前面加一个 reverse: 即可
    return HttpResponseRedirect(reverse('reverse:articles-year-redirect',args=(2020,)))
在模板中
    2020 Article
p' 来命名

在`reverseappurls.py`下
```python
app_name = 'reverse'  # 只要加一个这个即可
urlpatterns = [
    path('first_request_url/',views.first_request),
    path('articles//',views.articles_year,name='articles-year-redirect'),
]
在Python代码中

在reverseappviews.py下,

def first_request(request):
    # return HttpResponse('first-request')
	# 在name前面加一个 reverse: 即可
    return HttpResponseRedirect(reverse('reverse:articles-year-redirect',args=(2020,)))
在模板中
    2020 Article
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/783502.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号