浏览目录

  • 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' }  

注:分组和命名分组不能同时使用,位置参数取不到值,关键字相同,则全输出,否则覆盖正则表达式中命名分组捕获的值。

小总结 

我们现在掌握了三种向视图函数传递参数的方法:

  1. 在正则匹配模式中使用分组模式从请求的URL中捕获参数并以位置参数的形式传递给视图。

  2. 在正则匹配模式中使用命名分组模式从请求的URL中捕获参数并以关键字参数的形式传递给视图。

  3. 通过给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" ),
]