Django的URLconf

URL

概要

咱们要在Django项目中为应用程序设计URL,咱们能够建立一个名为URLconf(一般为urls.py)的Python模块。
这个模块是纯Python代码,是一个简单的正则表达式到Python函数(视图)之间的映射。html

这种映射关系能够很简短也能够很复杂。它还能够引用其余的映射关系。python

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都会调用适当的错误处理视图。

注意:shell

  1. 分组和命名分组不能同时使用。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',}
  2. 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'}

小总结:
咱们如今掌握了三种向视图函数传递参数的方法:

  1. 在正则匹配模式中使用分组模式从请求的URL中捕获参数并以位置参数的形式传递给视图。
  2. 在正则匹配模式中使用命名分组模式从请求的URL中捕获参数并以关键字参数的形式传递给视图。
  3. 经过给django.conf.urls.url()传递参数。

反向解析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。

name模式

在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中须要的参数:

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>

URL中须要关键字参数

例如:
在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>

namespace模式

咱们能够为每一个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的语法同上。

相关文章
相关标签/搜索