Django框架 之 URLconf
浏览目录
- URL
- 摘要
- Django如何处理一个请求
- 反向解析URL
- name模式
- namespace模式
一、URL
1、摘要
我们要在Django项目中为应用程序设计URL,我们可以创建一个名为URLconf(通常为urls.py)的Python模块。
这个模块是纯Python代码,是一个简单的正则表达式到Python函数(视图)之间的映射。
这种映射关系可以很简短也可以很复杂。它还可以引用其他的映射关系。
2、Django如何处理一个请求
如果用户请求一个由Django提供服务的站点,它将按照以下逻辑决定执行哪些代码:
1、通常不考虑中间件的情况下,Django将会确定要使用的根URLconf模块。
2、Django加载该Python模块并查找变量 urlpatterns,这个变量应该是一个由django.conf.urls.url() 实例组成的列表。
3、Django按照顺序遍历每一个URL模式,并停在与本次请求的URL匹配的第一个URL模式。
4、一旦一个正则表达式匹配上用户请求的URL,Django就会导入并调用给定对的视图,该视图是一个简单的Python函数(或基于类的视图)。
该视图将被传入以下参数:
①一个请求示例--request
②正则表达式中使用分组捕获的值将会以位置参数传递给视图。
③正则表达式中的命名分组捕获的值将会以关键方式传递给视图。
5、如果没有正则表达式匹配或者在此过程中发生了异常,Django都会调用适当的错误处理视图。
注意
1、分组和命名分组不能同时使用。
请求URL:
1
|
http:
/
/
127.0
.
0.1
:
8000
/
kwargs_test
/
123
/
abc
/
|
1
|
url(r
'^kwargs_test/(\d+)/(?P<name>\w+)/'
, views.kwargs_test),
|
视图:
1
2
3
|
def
kwargs_test(request,
*
args,
*
*
kwargs):
print
(args, kwargs)
return
HttpResponse(
"OK"
)
|
输出:
1
|
() {
'name'
:
'abc'
,}
|
注:位置参数取不到值。
2、django.conf.urls.url()的关键字参数会覆盖正则表达式中命名分组捕获的值。
请求URL:
1
|
http:
/
/
127.0
.
0.1
:
8000
/
kwargs_test
/
123
/
abc
/
|
1
|
url(r
'^kwargs_test/(\d+)/(?P<name>\w+)/'
, views.kwargs_test, {
"name1"
:
"yaya"
}),
|
视图:
1
2
3
|
def
kwargs_test(request,
*
args,
*
*
kwargs):
print
(args, kwargs)
return
HttpResponse(
"OK"
)
|
输出:
1
|
() {
'name'
:
'abc'
,
'name1'
:
'yaya'
}
|
注:分组和命名分组不能同时使用,位置参数取不到值,关键字相同,则全输出,否则覆盖正则表达式中命名分组捕获的值。
小总结
我们现在掌握了三种向视图函数传递参数的方法:
-
在正则匹配模式中使用
分组模式
从请求的URL中捕获参数并以位置参数
的形式传递给视图。 -
在正则匹配模式中使用
命名分组模式
从请求的URL中捕获参数并以关键字参数
的形式传递给视图。 -
通过给
django.conf.urls.url()
传递参数。
二、反向解析URL
在我们的Django项目中,我们经常会遇到要在视图中返回一个重定向到具体URL的响应,或者要将具体的URL地址嵌入到HTML页面中(如:a标签的href属性等)的情况,Django框架充分考虑了这种需求,所以提供了工具来反向解析(推导)出具体的URL。
1、name模式
在Django的URLconf中,我们可以通过给匹配模式起别名,然后我们可以通过别名来反向推导出具体的URL。
1.1、普通情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# urls.py
urlpatterns
=
[
# 为匹配模式起别名
url(r
'^student_list/'
, views.student_list, name
=
"students"
),
]
# 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
from
django.urls
import
reverse
def
add_student(request):
if
request.method
=
=
"POST"
:
# 根据别名反向推导出具体的URL,避免出现硬编码URL的情况。
url
=
reverse(
"students"
)
# 得到URL: /student_list/
return
redirect(url)
# HTML中
<a href
=
"{% url 'students' %}"
>点击查看所有学生信息<
/
a>
|
1.2、URL中需要位置参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# urls.py
urlpatterns
=
[
# 为匹配模式起别名,并且正则表达式中有分组匹配
url(r
'^student/(\d+)'
, views.student_detail, name
=
"student_detail"
),
]
# 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
from
django.urls
import
reverse
def
add_student(request):
if
request.method
=
=
"POST"
:
# 根据别名和位置参数反向推导出具体的URL,避免出现硬编码URL的情况。
url
=
reverse(
"student_detail"
, args
=
(
1
,))
# 得到URL:/student/1/
return
redirect(url)
# HTML中
<a href
=
"{% url 'student_detail' 1 %}"
>点击查看学生详细信息<
/
a>
|
1.3、URL中需要关键字参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# urls.py
urlpatterns
=
[
# 为匹配模式起别名,并且正则表达式中有分组匹配
url(r
'^student/(?P<num>\d+)'
, views.student_detail, name
=
"student_detail"
),
]
# 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
from
django.urls
import
reverse
def
add_student(request):
if
request.method
=
=
"POST"
:
# 根据别名和位置参数反向推导出具体的URL,避免出现硬编码URL的情况。
# 得到URL:/student/10/
url
=
reverse(
"student_detail"
, kwargs
=
{
"num"
:
10
})
return
redirect(url)
# HTML中
<a href
=
"{% url 'student_detail' num=10 %}"
>点击查看学生详细信息<
/
a>
|
2、namespace模式
我们的项目比较庞大,其URL可能成百上千,不可避免的会出现别名重复的情况。这个时候就需要使用namespace
了,我们可以为不同的urlpatterns
设置一个namespace
(命名空间),这样在不同的命名空间下即使别名相同,还是可以通过namespace
来区分不同的URL匹配模式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
# urls.py中
urlpatterns
=
[
# 为app01.urls设置命名空间名:beijing
url(r
'^beijing/'
, include(
"app01.urls"
, namespace
=
"beijing"
)),
# 为app02.urls设置命名空间名:shanghai
url(r
'^shanghai/'
, include(
"app02.urls"
, namespace
=
"shanghai"
)),
]
# app01/urls.py
urlpatterns
=
[
# app01/urls.py中有一个别名为index的匹配模式
url(r
'^index/$'
, views.index, name
=
"index"
),
]
# app02/urls.py
urlpatterns
=
[
# app02/urls.py中也有一个别名为index的匹配模式
url(r
'^index/$'
, views.index, name
=
"index"
),
]
# 视图views.py中
def
index(request):
# 通过 namespce:name 的方式来反向推导出准确的URL
url
=
reverse(
"shanghai:index"
)
# HTML中
<a href
=
"{% url 'shanghai:index' %}"
>上海分公司首页<
/
a>
|
app_name
也可以通过在app/urls.py中定义app_name
来设置app级别的namespace
1
2
3
4
5
6
|
# 在上面示例的app01/urls.py文件中:
app_name
=
"beijing"
urlpatterns
=
[
url(r
'^index/$'
, views.index, name
=
"index"
),
]
|
浏览目录
- URL
- 摘要
- Django如何处理一个请求
- 反向解析URL
- name模式
- namespace模式
一、URL
1、摘要
我们要在Django项目中为应用程序设计URL,我们可以创建一个名为URLconf(通常为urls.py)的Python模块。
这个模块是纯Python代码,是一个简单的正则表达式到Python函数(视图)之间的映射。
这种映射关系可以很简短也可以很复杂。它还可以引用其他的映射关系。
2、Django如何处理一个请求
如果用户请求一个由Django提供服务的站点,它将按照以下逻辑决定执行哪些代码:
1、通常不考虑中间件的情况下,Django将会确定要使用的根URLconf模块。
2、Django加载该Python模块并查找变量 urlpatterns,这个变量应该是一个由django.conf.urls.url() 实例组成的列表。
3、Django按照顺序遍历每一个URL模式,并停在与本次请求的URL匹配的第一个URL模式。
4、一旦一个正则表达式匹配上用户请求的URL,Django就会导入并调用给定对的视图,该视图是一个简单的Python函数(或基于类的视图)。
该视图将被传入以下参数:
①一个请求示例--request
②正则表达式中使用分组捕获的值将会以位置参数传递给视图。
③正则表达式中的命名分组捕获的值将会以关键方式传递给视图。
5、如果没有正则表达式匹配或者在此过程中发生了异常,Django都会调用适当的错误处理视图。
注意
1、分组和命名分组不能同时使用。
请求URL:
1
|
http:
/
/
127.0
.
0.1
:
8000
/
kwargs_test
/
123
/
abc
/
|
1
|
url(r
'^kwargs_test/(\d+)/(?P<name>\w+)/'
, views.kwargs_test),
|
视图:
1
2
3
|
def
kwargs_test(request,
*
args,
*
*
kwargs):
print
(args, kwargs)
return
HttpResponse(
"OK"
)
|
输出:
1
|
() {
'name'
:
'abc'
,}
|
注:位置参数取不到值。
2、django.conf.urls.url()的关键字参数会覆盖正则表达式中命名分组捕获的值。
请求URL:
1
|
http:
/
/
127.0
.
0.1
:
8000
/
kwargs_test
/
123
/
abc
/
|
1
|
url(r
'^kwargs_test/(\d+)/(?P<name>\w+)/'
, views.kwargs_test, {
"name1"
:
"yaya"
}),
|
视图:
1
2
3
|
def
kwargs_test(request,
*
args,
*
*
kwargs):
print
(args, kwargs)
return
HttpResponse(
"OK"
)
|
输出:
1
|
() {
'name'
:
'abc'
,
'name1'
:
'yaya'
}
|
注:分组和命名分组不能同时使用,位置参数取不到值,关键字相同,则全输出,否则覆盖正则表达式中命名分组捕获的值。
小总结
我们现在掌握了三种向视图函数传递参数的方法:
-
在正则匹配模式中使用
分组模式
从请求的URL中捕获参数并以位置参数
的形式传递给视图。 -
在正则匹配模式中使用
命名分组模式
从请求的URL中捕获参数并以关键字参数
的形式传递给视图。 -
通过给
django.conf.urls.url()
传递参数。
二、反向解析URL
在我们的Django项目中,我们经常会遇到要在视图中返回一个重定向到具体URL的响应,或者要将具体的URL地址嵌入到HTML页面中(如:a标签的href属性等)的情况,Django框架充分考虑了这种需求,所以提供了工具来反向解析(推导)出具体的URL。
1、name模式
在Django的URLconf中,我们可以通过给匹配模式起别名,然后我们可以通过别名来反向推导出具体的URL。
1.1、普通情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# urls.py
urlpatterns
=
[
# 为匹配模式起别名
url(r
'^student_list/'
, views.student_list, name
=
"students"
),
]
# 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
from
django.urls
import
reverse
def
add_student(request):
if
request.method
=
=
"POST"
:
# 根据别名反向推导出具体的URL,避免出现硬编码URL的情况。
url
=
reverse(
"students"
)
# 得到URL: /student_list/
return
redirect(url)
# HTML中
<a href
=
"{% url 'students' %}"
>点击查看所有学生信息<
/
a>
|
1.2、URL中需要位置参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# urls.py
urlpatterns
=
[
# 为匹配模式起别名,并且正则表达式中有分组匹配
url(r
'^student/(\d+)'
, views.student_detail, name
=
"student_detail"
),
]
# 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
from
django.urls
import
reverse
def
add_student(request):
if
request.method
=
=
"POST"
:
# 根据别名和位置参数反向推导出具体的URL,避免出现硬编码URL的情况。
url
=
reverse(
"student_detail"
, args
=
(
1
,))
# 得到URL:/student/1/
return
redirect(url)
# HTML中
<a href
=
"{% url 'student_detail' 1 %}"
>点击查看学生详细信息<
/
a>
|
1.3、URL中需要关键字参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# urls.py
urlpatterns
=
[
# 为匹配模式起别名,并且正则表达式中有分组匹配
url(r
'^student/(?P<num>\d+)'
, views.student_detail, name
=
"student_detail"
),
]
# 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
from
django.urls
import
reverse
def
add_student(request):
if
request.method
=
=
"POST"
:
# 根据别名和位置参数反向推导出具体的URL,避免出现硬编码URL的情况。
# 得到URL:/student/10/
url
=
reverse(
"student_detail"
, kwargs
=
{
"num"
:
10
})
return
redirect(url)
# HTML中
<a href
=
"{% url 'student_detail' num=10 %}"
>点击查看学生详细信息<
/
a>
|
2、namespace模式
我们的项目比较庞大,其URL可能成百上千,不可避免的会出现别名重复的情况。这个时候就需要使用namespace
了,我们可以为不同的urlpatterns
设置一个namespace
(命名空间),这样在不同的命名空间下即使别名相同,还是可以通过namespace
来区分不同的URL匹配模式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
# urls.py中
urlpatterns
=
[
# 为app01.urls设置命名空间名:beijing
url(r
'^beijing/'
, include(
"app01.urls"
, namespace
=
"beijing"
)),
# 为app02.urls设置命名空间名:shanghai
url(r
'^shanghai/'
, include(
"app02.urls"
, namespace
=
"shanghai"
)),
]
# app01/urls.py
urlpatterns
=
[
# app01/urls.py中有一个别名为index的匹配模式
url(r
'^index/$'
, views.index, name
=
"index"
),
]
# app02/urls.py
urlpatterns
=
[
# app02/urls.py中也有一个别名为index的匹配模式
url(r
'^index/$'
, views.index, name
=
"index"
),
]
# 视图views.py中
def
index(request):
# 通过 namespce:name 的方式来反向推导出准确的URL
url
=
reverse(
"shanghai:index"
)
# HTML中
<a href
=
"{% url 'shanghai:index' %}"
>上海分公司首页<
/
a>
|
app_name
也可以通过在app/urls.py中定义app_name
来设置app级别的namespace
1
2
3
4
5
6
|
# 在上面示例的app01/urls.py文件中:
app_name
=
"beijing"
urlpatterns
=
[
url(r
'^index/$'
, views.index, name
=
"index"
),
]
|