Python中国社区  »  Django

Django的路由系统

小小封 • 4 天前 • 17 次点击  
阅读 1

Django的路由系统

Django的路由系统

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表。

你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。

URLconf配置

基本格式

from django.conf.urls import url

urlpatterns = [
     url(正则表达式, views视图函数,参数,别名),
]
复制代码

注意:Django2.0版本中的路由系统已经替换成下面的写法(官方文档):

from django.urls import path

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),
]
复制代码

参数说明

  • 正则表达式:一个正则表达式字符串
  • views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
  • 参数:可选的要传递给视图函数的默认参数(字典形式)
  • 别名:一个可选的name参数

正则表达式详解

基本配置

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
复制代码

注意事项

  • 路由一旦匹配就不再走下面的路由匹配关系了
  • 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
  • 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles而不是^/articles。
  • 每个正则表达式前面的'r'是可选的但是建议加上。
  • 路由增加首页的方式 url(r'^$',views.home)
  • 路由增加尾页的方式(当所有的路径都匹配不上时,给我返回404提示信息) url(r'',views.error)

补充说明

是否开启URL访问地址后面不为/跳转至带有/的路径的配置项 APPEND_SLASH=True

Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加'/'。

分组命名匹配

上面的示例使用简单的正则表达式分组匹配(通过圆括号)来捕获URL中的值并以位置参数形式传递给视图。

在更高级的用法中,可以使用分组命名匹配的正则表达式组来捕获URL中的值并以关键字参数形式传递给视图。

无名分组

url(r'^test/([0-9]{4})/',views.test)

会将加了括号的正则表达式匹配的内容当做位置参数传递给后面的视图函数

有名分组 url(r'^test/(?P<year>\d+)/',views.test)

会将加了括号的正则表达式匹配的内容当做关键字参数传递给后面的视图函数

关键字就是尖括号里面的名字(year)

注意事项

  • 有名分组和无名不能混合使用!!!
  • 只要不混着用,有名分组和无名分组支持多个相同类型的传参

URLconf匹配的位置

URLconf 在请求的URL 上查找,将它当做一个普通的Python 字符串。不包括GET和POST参数以及域名。

例如,www.example.com/myapp/ 请求中,URLconf 将查找myapp/。

在http://www.example.com/myapp/?page=3 请求中,URLconf 仍将查找myapp/。

URLconf 不检查请求的方法。换句话讲,所有的请求方法 —— 同一个URL的POST、GET、HEAD等等 —— 都将路由到相同的函数。

捕获的参数永远都是字符串

每个在URLconf中捕获的参数都作为一个普通的Python字符串传递给视图,无论正则表达式使用的是什么匹配方式

反向解析

简单来说就是可以给我们的URL匹配规则起个名字,一个URL匹配模式起一个名字。

这样我们以后就不需要写死URL代码了,只需要通过名字来调用当前的URL。

前端反向解析
{% url 'add' %}  # {% url'放urls.py中路由与视图函数的name的值' %} 

后端反向解析
from django.shortcuts import reverse

url(r'^testadd123/$',views.testadd,name='add')

res = reverse('add')
复制代码

无名分组的反向解析

前端反向解析
	{% url 'add' 1 %}  # {% url '放urls.py中路由与视图函数的name的值' %} 
	
后端反向解析
	from django.shortcuts import reverse
	
	url(r'^testadd123/(\d+)/$',views.testadd,name='add')
	
	res = reverse('add',args=(1,))
复制代码

有名分组的反向解析

前端反向解析
	{% url 'add' 1 %}  # {% url '放urls.py中路由与视图函数的name的值' %}   推荐你用这种
	
	<a href="{% url 'add' year=1 %}">999</a>
后端反向解析
	res = reverse('add',args=(1,))  # 推荐你用这种
	
	res = reverse('add',kwargs={'year':1})
复制代码

注意: 当命名你的URL 模式时,请确保使用的名称不会与其它应用中名称冲突。如果你的URL 模式叫做comment,而另外一个应用中也有一个同样的名称,当你在模板中使用这个名称的时候不能保证将插入哪个URL。

在URL 名称中加上一个前缀,比如应用的名称,将减少冲突的可能。我们建议使用myapp-comment 而不是comment。

名称空间模式

在不同的APP使用相同的URL名称,如果不区分,会导致路由解析错误,而URL的命名空间模式也可以让你唯一反转命名的URL。

语法

'命名空间名称:URL名称'

django2.0版的path

django2.0的re_path和1.0的url一样

path转化器

文档原文是Path converters,暂且翻译为转化器。

Django默认支持以下5个转化器:

str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
复制代码

注册自定义转化器

对于一些复杂或者复用的需要,可以定义自己的转化器。转化器是一个类或接口,它的要求有三点:

  • regex 类属性,字符串类型
  • to_python(self, value) 方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。
  • to_url(self, value) 方法,和 to_python - 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。 例子:
需要三步走战略
# 自定义转换器
class FourDigitYearConverter:
	regex = '[0-9]{4}'
	def to_python(self, value):
		return int(value)
	def to_url(self, value):
		return '%04d' % value
register_converter(FourDigitYearConverter, 'yyyy')

urlpatterns = [
	path('admin/', admin.site.urls),
	# path('index/<int:id>/',index ),
	# path('index/<str:id>/',index ),
	path('login/<yyyy:name>/',index)

]
复制代码
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/31676
 
17 次点击  
分享到微博