网址的对应与委派
Django 1.x 和 Django 2.0 之后网址的对应和委派方法不同。在 Django 2.0 之后的版本对于网址的对应和委派方法大幅度简化。原有的方法虽有保留,但是在操作上还是要进行一定幅度的调整。
一、Django网址架构
和使用PHP网站不同的地方在于:Django 中全部是以一般的路径网址来表示,在网址上基本上不会出现文件的名称(例如,index.php),也不会有特殊符号。
1、URLconf 简介
Django 使用的是URLconfig 这个 Python 模块来作为网址的解析并且对应到 views.py 中函数的主要处理者。需要注意的是,在 Django 2.0 版本之前网址的对应主要是正则表达式(Regular Expression)来设置对应的网址以及对应的参数格式。而在 Django 2.0 之后的版本则是用定义的路由字符串来进行解析。
URLconf 处理网址的步骤大致如下:
(1)首先在 settings.py 中找到 ROOT_URLCONF 的设置,决定使用哪个模块来进行操作。一般来说这个设置都不需要更改。例如,在我们常见一个Django项目后,这个项目会自动地添加以下的指令:
ROOT_URLCONF = 'DjangoProjects.urls'
(2)加载上述指定的模块,然后找到 urls.py 中的 urlpatterns 变量根据其中的设置来找到对应的要处理的网址和函数,它必须要是 django.urls.path (Django 2.0 之后)或者是 django.urls.re_path (Django 2.0 之前)
例如,如下代码:
from django.urls import path
from django.contrib import admin
from myblog.views import homepage
urlpatterns = [
path('admin/', admin.site.urls),
path('', homepage),
]
在第一行导入的是 Django 2.0 之后处理 url 的专用模块,在 Djano 2.0之前使用的是正则化来实现路由的处理,上诉代码对应的改为:
from django.urls import re_path
from django.contrib import admin
from myblog.views import homepage
urlpatterns = [
re_path(r'^admin/', admin.site.urls),
re_path(r'^$', homepage),
]
注意到这里,两个版本对主页的处理是不一样。
在 2.0 之后的版本,用空字符串来表示主页。
而在 2.0 之前的版本表示方法相对比较复杂,下面再简单介绍一下:
其中,字符串之前的 " r " 的作用是要求 Python 解释器保持后面字符串的原貌,这也是使用 RE 解析的字符串都会开的“保险”。而**“ ^ ”** 表示接下来的字符要定义的开头的字符串,而**“ $ ”** 表示结尾字符串。
开始和结尾放在一起,中间没有任何字符串就表示的是首页。
(3)按照 urlpatterns 的顺序,一个一个往下核对网址和路由字符串中的设置 pattern 。
(4)连接到 views.py 中的函数。
(5)如果找不到合适的 pattern,就会产生一个例外,交由错误处理程序。
2、委派到各个的网址到处理函数
在Django 2.0 之后,网址的委派从正则表达式改为了字符串和 Path Converter (路由转换器),变得更加方便和简洁。
Path Converter 是当网址要携带参数给函数时路由所要定义的内容。
例如,把 http://(你的网址)/about 委派到 about 函数,把 http://(你的网址)/list 委派到 listing 函数只需要将 urlpatterns 写入如下的内容即可:
urlpatterns = [
path('admin/', admin.site.urls),
path('', homepage),
path('about/', about),
path('list/', listing),
]
需要注意的是 about 和 listing 后面的 ‘ / ’ 非常重要,每个 pattern 必须以 ’ / ’ 作为结束的标志,如果没有就无法正确的定位。
我们在网页栏上输入网址时,即使没有加上 ’ / ’ ,它也会被浏览器自动的加上。
3、urlpatterns的正则表达式的说明
由于兼容性的需求,有许多现有的模块和Django的程序代码现在仍使用的是旧版的正则表达式的方式进行网址的对应和委派。
常用在网址上的符号如下表:
符号 | 说明 |
---|---|
^ | 指定起始字符或字符串,如放在 【】中则表示否定 |
$ | 指定终止符或字符 |
. | 任何一种字符都符合 |
所有的字母以及数字包含(‘ / ’) | 对应到原有字符 |
[…] | 中括号中的内容用来表示一个字符的格式设置 |
\d | 任何一个数字字符,等于[0 - 9] |
\D | 非数字字符,等于[ ^ 0 - 9] |
\w | 任何一个字母或数字字符,等于[ a-z A-Z 0-9 ] |
\W | 任何一个非上述字符,等于[ ^ a-z A-Z 0-9 ] |
? | 代表前面一个字符样式可以重复出现0次或1次 |
* | 代表前面一个字符样式可以重复出现0次或0次以上 |
+ | 代表前面一个字符样式可以重复出现1次或1次以上 |
{m} | 大括号中间的数字m,代表前一字符可以出现m次 |
{m.n} | 代表前一字符可以出现m~n次 |
| | 或,即两种格式设置任何一种都可以 |
(…) | 小括号中间若匹配,则取出成为任一参数 |
(?P<name>) | 同上,但是指定此参数名称为name |
例如,上一小节的urlpatterns,改为2.0之前的正则表达式为:
urlpatterns = [
re_path('^admin/$', include(admin.site.urls)),
re_path('^$', homepage),
re_path('^about/$', about),
re_path('^list/$', listing),
]
值得注意的是,在 about、list 后面的 ’ \ ’ 和 ’ $ ’ 非常重要。不过前者在输入网址时会被自动加入。
以 about 为例,如果没有加上 ’ $ ’ ,那么以 about/ 开头的网址都会被匹配。
正则表达式的使用,例:
re_path(r'^list/(?P<list_date>\d{4}/\d{1,2}/\d{1,2})$',view.listing)
例如这行代码,就是对应网址为 list/年/月/日 的语句,其中年月日的位数分别为 4位/(1或2)位/(1或2)位数字,最后以 list_date 的名称取出作为参数。
二、高级设置技巧
当设计的网站项目越来越大、功能越来越多时,所用到的网址对应与委派也越来越复杂。因此,运用一些小技巧可以使代码更简单、更易读。
1、参数的传送
有时我们在进行参数传递的时候,可能需要设定一些预设的值也就是默认值一边降低网址设计的复杂度。
例如,在一个书籍网站中,我们在显示关于作者信息的时候,如果有指定的数字,则显示指定信息对应的作者的信息。如果没有,则以第0位作者作为显示的目标:
path('about/', views.about),
path('about/\<int:author_no>/', views.about),
然后在 about 函数中的自变量行加上一个默认值:
def about(request, author_no = 0):
html = "here is Author:{}".format(author_no)
return HttpResponse(html)
2、include 其他整组的 urlpatterns 设置
大型网站如果像之前一条一条的设置的话,会越来越复杂,urlpattrns 里面的语句也会越来越多,非常不利于维护。因此,对于同样性质的网页,使用 include 的方式把 urlspatterns 放到另一个地方去设置会方便许多。
例如:
my_patterns = [
path('company/', views.company)
path('sales/', views.sales)
path('contact/', views.contact)
]
urlpatterns = [
path('info/',include(my_pattrns))
]
3、URLconf的反解功能
如果我们需要在一个网址中插入一个或者多个链接,也可以用设计好的 patter 来产生匹配格式的网址。
例如:
path('post/\<int:year>/\<int:month>/\<int:day>', view.post, name = 'post-url')
这里我们建立一个按日期为后续网址栏参数的网址,并将它命名为 post-url 。
这时我们要在网页中显示,对应的 .html 文件中代码为:
{% url 'post-url' 2019 10 22 %}
这里表示,要以(2019,10,22)这四个数字为自变量传入到 post-url 的 pattern 中。