咱们要在Django项目中为应用程序设计URL,咱们能够建立一个名为URLconf(一般为urls.py)的Python模块。
这个模块是纯Python代码,是一个简单的正则表达式到Python函数(视图)之间的映射。html
这种映射关系能够很简短也能够很复杂。它还能够引用其余的映射关系。python
若是用户请求一个由Django提供服务的站点,它将按照如下逻辑决定执行哪些代码:正则表达式
根URLconf
模块。urlpatterns
,这个变量应该是一个由django.conf.urls.url()
实例组成的列表。request
。分组
捕获的值将做为位置参数传递给视图。命名分组
捕获的值将会以关键字方式传递给视图,可是它能够被直接传参方式覆盖。注意:shell
分组和命名分组不能同时使用。django
请求URL:http://127.0.0.1:8000/kwargs_test/123/abc/
app
url(r'^kwargs_test/(\d+)/(?P<name>\w+)/', views.kwargs_test),
视图:框架
def kwargs_test(request, *args, **kwargs): print(args, kwargs) return HttpResponse("OK")
输出:函数
() {'name': 'abc',}
django.conf.urls.url()的关键字参数会覆盖正则表达式中命名分组捕获的值。工具
请求URL:http://127.0.0.1:8000/kwargs_test/123/abc/
编码
url(r'^kwargs_test/(\d+)/(?P<name>\w+)/', views.kwargs_test, {"name1": "Q1mi"}),
视图:
def kwargs_test(request, *args, **kwargs): print(args, kwargs) return HttpResponse("OK")
输出:
() {'name': 'abc', 'name1': 'Q1mi'}
小总结:
咱们如今掌握了三种向视图函数传递参数的方法:
分组模式
从请求的URL中捕获参数并以位置参数
的形式传递给视图。命名分组模式
从请求的URL中捕获参数并以关键字参数
的形式传递给视图。django.conf.urls.url()
传递参数。在咱们的Django项目中,咱们常常会遇到要在视图中返回一个重定向到具体URL的响应,或者要将具体的URL地址嵌入到HTML页面中(如:a标签的href属性等)的状况。
咱们以前一般都会选择硬编码(写死)的方式来实现相似上述的需求,可是这并非最优的解决办法。
例如:
在视图函数中:
def add_student(request): if request.method == "POST": ... return redirect("/student_list/") # 将URL硬编码到视图中 ...
在模板文件的HTML文件中:
<a href="/student_list/">点击查看全部学生信息</a>
Django框架充分考虑了这种需求,因此提供了工具来反向解析(推导)出具体的URL。
在Django的URLconf中,咱们能够经过给匹配模式起别名,而后咱们能够经过别名来反向推导出具体的URL。
例如:
在urls.py中:
urlpatterns = [ url(r'^student_list/', views.student_list, name="students"), # 为匹配模式起别名 ... ]
在视图中:
经过使用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文件中,使用下面的语法来反向推导出URL:
<a href="{% url 'students' %}">点击查看全部学生信息</a>
当咱们的匹配模式中的正则表达式有分组或命名分组的时候该怎么办呢?
也就是咱们仅仅经过别名没法推导出具体的URL时,该怎么办呢?
咱们能够在反向推导URL的时候传递URL中须要的参数:
例如:
在urls.py中:
urlpatterns = [ # 为匹配模式起别名,而且正则表达式中有分组匹配 url(r'^student/(\d+)', views.student_detail, name="student_detail"), ... ]
像上面的状况,咱们就无法简单的经过别名来推导出具体的URL。
咱们在反向推导URL的时候就须要传递参数了。
在视图中:
经过使用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文件中,使用下面的语法来反向推导出URL:
<a href="{% url 'student_detail' 1 %}">点击查看学生详细信息</a>
例如:
在urls.py中:
urlpatterns = [ # 为匹配模式起别名,而且正则表达式中有分组匹配 url(r'^student/(?P<num>\d+)', views.student_detail, name="student_detail"), ... ]
像上面的状况,咱们就无法简单的经过别名来推导出具体的URL。
咱们在反向推导URL的时候就须要传递参数了。
在视图中:
经过使用django.urls.reverse
根据上面的别名反向推导出URL。
from django.urls import reverse def add_student(request): if request.method == "POST": ... # 根据别名和位置参数反向推导出具体的URL,避免出现硬编码URL的状况。 url = reverse("student_detail", kwargs={"num": 10}) # 获得URL:/student/10/ return redirect(url) ...
在模板语言的HTML文件中,使用下面的语法来反向推导出URL:
<a href="{% url 'student_detail' num=10 %}">点击查看学生详细信息</a>
咱们能够为每一个URL的匹配模式设置一个别名,而后经过别名来反向推导出URL。这样的设置在小型项目也就是URL比较少的状况下是彻底够用的。
可是一旦咱们的项目比较庞大,其URL可能成百上千,不可避免的会出现别名重复的状况。
这个时候就须要使用namespace
了,咱们能够为不一样的urlpatterns
设置一个namespace
(命名空间),这样在不一样的命名空间下即便别名相同,仍是能够经过namespace
来区分不一样的URL匹配模式。
在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"), ]
如今咱们就能够经过namespace来区分上面两个别名为index
的匹配模式来反向推导出准确的URL了。
在视图中:
def index(request): # 经过 namespce:name 的方式来反向推导出准确的URL url = reverse("shanghai:index") ...
在模板语言的HTML中:
<a href="{% url 'shanghai:index' %}">上海分公司首页</a>
也能够经过在app/urls.py中定义app_name
来设置app级别的namespace
。
例如:
在上面示例的app01/urls.py文件中:
app_name = "beijing" urlpatterns = [ url(r'^index/$', views.index, name="index"), ... ]
在这种状况下反向推导URL的语法同上。