(4) Django - URL的编写规则
本文开始之前,应该已通过以下命令创建了项目mysite
和App index
。
URL编写的规则
在Django开发中,为使开发更加规范,通常在每个App中设置独立的静态资源和模板文件夹,并添加一个空白的urls.py
文件,将属于App的URL都写入到该文件中,而项目根目录的urls.py
是将每个App的urls.py
统一管理。当程序收到用户请求时,首先在根目录的urls.py
查找该URL是属于哪个App,然后在从App的urls.py
找到具体的URL信息。
在根目录mysite文件夹中的urls.py编写URL规则如下所示:
#根目录mysite的urls.py
#导入Admin模块
from django.contrib import admin
#导入URL编写模块
from django.urls import path, include
#整个项目的URL集合,每个列表元素代表一条URL信息
urlpatterns = [
path('admin/', admin.site.urls),#设定Admin的URL
path('', include('index.urls')),#URL为空,代表为网站的域名,通常是网站的首页;include将该URL分发给index的urls.py处理
]
下一步需要编写 index 的urls.py
文件,代码如下:
#index的urls.py
#导入URL编写模块
from django.urls import path
#导入当前目录下的views.py文件
from . import views
urlpatterns = [
path('', views.index)#通过views下的index函数处理请求并返回网页内容给用户
]
再下一步就是编写views.py
文件中视图函数index了,代码如下:
#index的views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("hello world")
启动MyDjango项目,在浏览器中打开http://127.0.0.1:8000/,运行结果如下:
image.png
在实际开发中,可以先编写视图函数,然后在设置app中的urls.py,最后设置根目录的urls.py。
URL变量
在日常开发中,有时候一个URL可以代表多个不同页面,如编写带有日期的URL。Django在编写URL时,可以对URL设置变量值,使URL具有多样性。
URL的变量类型有字符类型、整形、slug和uuid,最常用的是字符型和整型。
- 字符类型:匹配任何非空字符串,但不含斜杆。默认使用该类型。
- 整型:匹配0和正整数。
- slug:可理解为注释、后缀或附属等概念,常作为URL的解释性字符,比如网页的标题是“13岁的孩子”,其URL地址可设置为“13-sui-de-hai-zi”。
-
uuid:匹配一个uuid格式的对象。
根据上述变量类型,在 index 的urls.py
中添加带有字符型、整型和slug的URL地址信息,如下:
#index的urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
#添加带有字符类型year、整型month、slug类型day的URL
path('<year>/<int:mongth>/<slug:day>', views.mydate),
]
如上所见,在URL中使用变量符号“<>”可以为URL设置变量,在括号中以冒号分为两部分,前面是变量类型,后面是变量名,变量名可自行命名。
然后在views.py中编写视图函数mydate的处理方法,如下:
#views.py的 mydate 函数
def mydate(request, year, month, day):
return HttpResponse(str(year) + '/' + str(month) + '/' + str(day))
在浏览器上输入http://127.0.0.1:8000/2019/03/04,运行结果如下:
image.png
但是,在上述例子中的变量没有进一步规范日期格式,使得只要符合数据类型的变量值都可以运行,因此这里可以使用正则表达式限制URL的可变范围,如下:
#index的urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
path('', views.index),
#添加带有字符类型year、整型month、slug类型day的URL
## path('<year>/<int:month>/<slug:day>', views.mydate),
re_path('^(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})$', views.mydate)
]
在以上代码中,首先导入re_path模块,接下来在urlpatterns中就是使用re_path()来定义url,而不是path()。re_path()函数的作用是对URL变量进行截取和判断,以小括号表示,每个小括号的前后可以使用斜杆或其他字符将其分割。以上述代码为例,分别将变量year、month和day以斜杆分割,每个变量以一个小括号为单位,在小括号内,可分为三部分:
- ?P 是固定格式
- <year> 为变量的编写规则
- [0-9]{4} 是正则匹配模式,代表变量长度为4,取0-9之间的整数
需要注意的是,如果URL信息的开头或结尾是正则表达式,那么在表达式的开头 ^ 符号或结尾的 $ 符号是不能少的,否则开头的表达式或结尾的表达式部分就不能生效,在浏览器上输入无限长字符,程序也能正常访问。
设置参数name
除了在URL里面设置变量之外,Django还可以对URL进行命名。为你的 URL 取名能使你在 Django 的任意地方唯一地引用它,尤其是在模板中。这个有用的特性允许你只改一个文件就能全局地修改某个 URL 模式。使用该参数有利于URL的变更和维护,只要参数name的值不变,无论URL地址信息如何修改都无须修改模板中标签的href属性值。
在 index 的urls.py
、views.py
和模板myyear.html
中添加以下代码:
from django.shortcuts import render
#在urls.py添加新的URL信息
re_path('^(?P<year>[0-9]{4})$', views.myyear, name='myyear'),
在views.py添加对应的视图函数
def myyear(request, year):
return render(request, 'myyear.html')
#在templates文件夹添加myyear.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div><a href="/2019.html">2019 old Archive</a></div>
<div><a href="{% url 'myyear' 2019 %}">2019 Archive</a></div>
</body>
</html>
image.png
在上述模板文件myyear.html
中分别设置了两个标签a,虽然两个标签a的href属性值得写法不同,但实质上两者指向同一个URL地址。
设置额外参数
还有一种参数类型是以字典的数据类型传递的,该参数必须是字典格式,且只能在视图函数中读取和使用,参数值没有数据格式限制,可以为对象、字符串或列表(元组)等。
#带字典参数的URL,month的值也可以是{'month':('one','two')}等等其他格式。
re_path('^(?P<year>[0-9]{4})$', views.myyear_dict, {'month':'05'}, name='myyear_dict'),
#带字典参数的URL的视图函数
def myyear_dict(request, year, month):
return render(request, 'myyear_dict.html', {'month':month})
#在templates文件中添加myyear_dict.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="{% url 'myyear_dict' 2019 %}">2019 {{ month }} Archive</a>
</body>
</html>
上述代码中,通过url向视图函数myyear_dict传入了参数{‘month’:‘05’},在视图函数中又将month的值传递到html模板并生成网页返回给了用户。
带额外参数的url