在Django中,URL是Web服务的入口,用户通过浏览器发送的请求都传递到特定的URL地址,然后得到相应。在Django项目中,编写路由即公开接收哪些URL请求,而不在路由中定义的URL将不会被处理或返回。简而言之,URL路由可以被视为Web服务对外公开的API。Django遵循DRY原则,提倡使用简洁而优雅的URL。
概述
设计应用程序的URL时,可以创建一个称为URLconf(URL配置)的Python模块。这个模块是纯Python代码,负责将URL路径与Python函数(即视图)进行映射。这种映射可以根据需要缩短或延伸,也可以引用其他映射。由于是纯Python代码,因此可以进行动态构造。Django还提供了根据活动语言翻译URL的方法。
如何处理请求
当用户请求页面时,Django根据以下逻辑执行操作:
- 决定要使用的根URLconf模块,通常是由ROOT_URLCONF设置的值决定,但如果HttpRequest对象具有urlconf属性(由中间件设置),则将使用该值代替ROOT_URLCONF设置。
- 加载该模块并查找可用的urlpatterns,即django.conf.urls.url()实例的列表。
- 依次匹配每个URL模式,停在与请求的URL相匹配的第一个模式处。URL匹配是从上到下的短路操作,因此URL在列表中的位置非常关键。
- 导入并调用与匹配行中给定的视图相对应的函数。视图是一个简单的Python函数(称为视图函数)或基于类的视图。视图将接收HttpRequest实例以及匹配的正则表达式返回的值作为参数。
- 如果没有匹配到正则表达式,或者在过程中出现异常,则调用适当的错误处理视图。
转换器
path转换器
在Django 2.0及以上版本中,默认使用path转换器,示例如下:
from django.urls import path from . import views urlpatterns = [ path('articles/2003/', views.special_case_2003), path('articles/<int:year>/', views.year_archive), path('articles/<int:year>/<int:month>/', views.month_archive), path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail), ]
注意:
- 使用尖括号捕获URL中的值,而不是圆括号。
- 可以使用转换器指定捕获值的类型,例如
<int:year>
。 - 默认情况下,捕获的结果保存为字符串类型。
re_path转换器(旧版的url)
Django 2.0的url配置改为了path方法,但为了向后兼容,可以使用re_path方法代替path方法:
from django.urls import path, re_path from . import views urlpatterns = [ path('articles/2003/', views.special_case_2003), re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail), ]
与path方法不同之处在于:
- 使用正则表达式进行匹配。
- 所有传递给视图的参数都是字符串类型。
有名分组
使用命名的正则表达式组进行匹配,将捕获的值作为关键字参数传递给视图函数:
from django.urls import path, re_path from app01 import views urlpatterns = [ re_path(r'^articles/2003/$', views.special_case_2003), re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), ]
路由分发
通常,每个应用程序都会创建一个urls.py路由模块,然后从根路由转发到相应的urls.py模块。路由转发可以使用include()方法,也可以使用url()实例的列表。
from django.conf.urls import include, url urlpatterns = [ # ... 省略 ... re_path(r'^community/', include('django_website.aggregator.urls')), re_path(r'^contact/', include('django_website.contact.urls')), # ... 省略 ... ]
反向解析
在Django项目中,常见的需求是获取URL的最终形式,用于嵌入生成的内容或服务器端导航。Django提供不同的工具用于URL反解:
在模板中使用url模板标签:
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
在Python代码中使用reverse()函数:
from django.urls import reverse from django.http import HttpResponseRedirect def redirect_to_year(request): year = 2006 return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
名称空间
为了避免URL命名冲突,可以使用命名空间。在项目的urls.py中,通过include()方法指定命名空间,然后在各个应用的urls.py中定义命名空间。
urlpatterns = [ re_path(r'^app01/', include("app01.urls", namespace="app01")), re_path(r'^app02/', include("app02.urls", namespace="app02")), ]
以上是对Django路由控制URL的详细解释,希望能帮助理解和使用Django中的URL路由机制。
暂无评论内容