Django的URL路由配置Django如何处理一个请求实例路径转换器通过浏览器访问服务使用正则表达式:使用未命名的正则表达式组(不推荐)关于404的错误关于子路由路由的反向解析关于重定向
一个优雅干净的URL方案是高质量Web应用程序中的一个重要细节
Django可以让你自己设计URL,没有框架的限制
要为应用程序设计URL,您可以非正式的创建一个名为**URLconf(URL配置)的Python模块
这个模块是纯Python代码,是一个简单的Python模式(简单的正则表达式)到Python函数(您的视图)之间的映射
Django如何处理一个请求
当用户从Django的站点请求页面时,Django系统遵循以下步骤来执行Python的代码:
首先Django确定要使用的根URLconf模块,通过ROOT_URLCONF来设置,具体在settings.py配置文件中。但是如果传入HttpRequest对象具有urlconf属性(由中间件设置),则其值将用于替换ROOT_URLCONF设置
Django加载该Python模块并查找该变量urlpatterns。他是django.urls.path()和(或)djamgo.urls.re_path()实例的序列(sequence)
Django按顺序运行每个URL模式,并在匹配所有请求的URL的都一个请求中停止
一旦正则表达式匹配,Django将导入并调用给定的视图,这是一个简单的Python函数(或者基于类的视图),该视图会获得如下的参数:
一个HttpRequest实例
如果匹配的正则表达式没有返回任何命名组,那么来自正则表达式的匹配将作为文职参数提供
关键字参数由正则表达式匹配的任何命名组组成,由可选kwargs参数中指定的任何参数覆盖。django.urls.path()、django.urls.re_path()
如果没有正则表达式匹配,或者在此过程中的任何一点出现异常,Django将调用适当的错误处理视图
实例
from django.urls import path
from .import views
urlpatterns = [
path('add/2003/',views.special_cases_2003),
path('add//',views.year_archve),
path('add///',views.month_archive),
path('add////',views.article_detail),
]
说明:
要从URL中捕获一个值,请使用尖括号括起来
捕获的值可以选择包括转换器类型,例如,用于int:name捕获整数参数,如果不包括转换器/,则匹配字符以外的任何字符串
无需添加斜杠,因为每个URL都该有斜杠,例如articles,不是/articles。
实例请求:
/articles/2005/03/将匹配列表中的第三个条目。Django会调用该函数。views.month.archive(request,'2005','03')
/articles/2005/3/不符合任何网址格式,因为第三个条目需要两个数字的月份
/articles/2003/将匹配列表中的第一个模式,而不是第二个模式,因为模式是按顺序调试的,第一个模式是第一个测试通过,随意利用这些命令插入特殊情况,在这里,Django会调用该函数views.special-cases_2003(request)
/articles/2003将不匹配任何这些模式,因为每个URL都是以斜杠结尾的
/articles/2003/03/03/将匹配最终的模式。Django会调用该函数,views.article_detail(request,'2003','03','03')
路径转换器
默认情况下,以下路径转换器可用:
str- 匹配任何非空字符串,但是路径分隔符除外’/‘,如果表达式中不包括转换器,则为默认设置
int-匹配0或者任何正整数,返回一个int
slug:-匹配由ASCLL字母或者数字以及连字符和下划线在字符组成的任何形式地字符串。例如,building-your-lst-django-site.
uuid-匹配格式化的uuid,为了防止多个URL映射到同一个页面,必须包含破折号并且字母必须小写。例如,908908908099089786-23431-1232。返回一个uuid实例
path-匹配任何非空字符串,包括路径分隔符’/‘。这样,您就可以匹配完整的URL路径,而不是像一样匹配URL路径的一部分str
通过浏览器访问服务
注意:url路由,自上而下进行匹配,如果在上面就能匹配成功,则不会向下匹配
通过浏览器访问服务 127.0.0.1:8000/abc ==> root url(根路由) ==>加载子路由(myweb/urls.py) ==>正则匹配访问路径(path) ==> 视图函数(views.index) ==>views.py index()响应内容
使用正则表达式:
如果路径和转换器不足以定义URL模式,则还可以使用正则表达式,为此re_path()代替path()
在Python正则表达式中命名正则表达式组的语法为(?
前边的实例,使用正则表达式重写:
from django.urls import path,re_path
from .import views
urlpatterns = [
path('articles/2003/',views.specail_cases_2003),
re_path(r'^article/?P[0-9]{4}/$',views.year_archive),
re_path(r'^article/?P[0-9]{4}/(?P[0-9]{2})/$',views.month_archive),
re_path(r'^article/?P[0-9]{4}/(?P[0-9]{2})/(?P[\w-])/$',views.article)
]
这可以完成与上一个示例大致相同的操作,除了:
将要匹配的确切的url受到很多的限制,比如,年份1000/0将不再匹配,因为年份整数被限制为4
无论正则表达式进行那种匹配,每个捕获的参数将作为字符串发送到视图
当从使用切换为使用path(),re_path()反之为亦然时,特别重要的是要注意视图参数的类型可能会更改,因此您可能需要调整视图
使用未命名的正则表达式组(不推荐)
除了命名组语法(例如)之外(?P
不建议特点使用此用法,因为这样可以更轻松地在匹配的预期含义和视图的参数之间意外引入错入
无论哪种情况,建议在给定的正则表达式仅使用一种形式,当两种样式,当两种样式混合使用时,任何未命名的组都会被忽略,只有命名的组才会传递到视图函数
关于404的错误
404的错误页面,在模板目录中创建一个404.html的页面
在配置文件中settings.py配置DEBUG = False
在配置文件中settings.py配置TEMPLATE = [{'DIRS':[os.path.join(BASE_DIR,"templates")]}]
同时需要在项目的根目录下创建文件夹template,并且在此目录下创建一个404.html文件
在出现404的情况时,自动寻找404页面
还可以在视图函数中手动报出404错误信息,带提示信息
在视图函数中可以指定返回一个404
注意:Http404需要在django.http的模块中引入 # 响应 404 raise Http404('纳尼')
在模板中404.html
404
404 not found
{{exception}}
关于子路由
当项目越来越大,程序越来越多,路由越来越多时,我们可以创建子路由来方便管理与查看
myweb/urls.py中的主路由写法
from django.urls import path,include
from myapp.urls import *
urlpatterns = [
path('myapp/', include('myapp.urls')),
]
myapp/urls.py中的子路由写法
from django.urls import path
from .import views
urlpatterns = [
path('index',views.index),
path('add',views.add)
]
路由的反向解析
# 路由
from django.urls import re_path
from .import views
urlpatterns = [
path('',views.index,name='find1'),
path('find',views.find,name='fin2'),
path('find//',views.find,name='find3')
]
# 页面展示
/
/find
/find/100/lisi
关于重定向
在python代码中:
from django.http import HttpResponseRedirect
from django.urls import reverse
def redirect_to_year(request):
year = 2019
return HttpResponseRedirect(reverse('news-year-archive',args=(year,)))
或简写
from django.urls import reverse
from django.shortcuts import redirect
def index(request):
year = 2019
return redirect(reverse('news-year-archive',args=(year,)))