URL

概要

我们要在Django项目中为应用程序设计URL,我们可以创建一个名为URLconf(通常为urls.py)的Python模块。
这个模块是纯Python代码,是一个简单的正则表达式到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都会调用适当的错误处理视图。

注意:

  1. 分组和命名分组不能同时使用。

    请求URL:
    http://127.0.0.1:8000/kwargs_test/123/abc/

    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的语法同上。

Django的URLconf的更多相关文章

  1. django 配置URLconf和获取值

    django中正确配置url匹配找到视图: 1 在项目下的settings.py中ROOT_URLCONF = "项目名.urls" 表示 前台发来请求会先去项目下的test3/u ...

  2. Django框架 之 URLconf

    Django框架 之 URLconf 浏览目录 URL 摘要 Django如何处理一个请求 反向解析URL name模式 namespace模式 一.URL 1.摘要 我们要在Django项目中为应用 ...

  3. [Python] 利用Django进行Web开发系列(二)

    1 编写第一个静态页面——Hello world页面 在上一篇博客<[Python] 利用Django进行Web开发系列(一)>中,我们创建了自己的目录mysite. Step1:创建视图 ...

  4. 【Python】django表单与提交

    参考:http://djangobook.py3k.cn/2.0/chapter07/ 本文的内容应属于django的表单模块,没有涉及到的后端request对象的处理方法可以单独深入学习表单. UR ...

  5. Django视图函数

    一.视图函数 1. 视图函数的第一个参数一定是一个HTTPRequest类型的对象,这个对象是Django自动创建的,具体形参名通常用request.通过这个对象,可以调用请求的一些参数,比如requ ...

  6. django HTTP请求(Request)和回应(Response)对象

    Django使用request和response对象在系统间传递状态.—(阿伦)当一个页面被请示时,Django创建一个包含请求元数据的 HttpRequest 对象. 然后Django调入合适的视图 ...

  7. Django的请求流程(url)

    一.Django是怎么处理请求的? 当你通过在浏览器里敲http://127.0.0.1:8000/hello/来访问Hello world消息得时候,Django在后台有些什么动作呢? 所有均开始于 ...

  8. [R]django的HTTPREQUEST对象

    django的HTTPREQUEST对象 via Django使用request和response对象 当请求一张页面时,Django把请求的metadata数据包装成一个HttpRequest对象, ...

  9. django(二)视图和URL配置

    创建一份视图: 在上一节,使用django-admin.py startproject制作的mysite文件夹中,创建一个叫做views.py的空文件.这个Python模块健柏寒这一章的视图. vie ...

随机推荐

  1. Linux设备驱动程序 之 get_free_page

    get_free_page 如果模块需要分配大块的内存,使用面向页的分配会有很多优点: 分配页面可使用下面的函数: unsigned long get_zeroed_page(gfp_t gfp_ma ...

  2. 彻底搞清楚javascript中的require、import和export(js模块加载规范的前世今生)

    为什么有模块概念 理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块. 但是,Javascript不是一种模块化编程语言,在es6以前,它是不支持”类”(class),所以也 ...

  3. 使用.NET Framework开发IIS 7.0模块和处理程序拦截请求实现跳转

    扩展IIS的两种方法:模块与处理程序. 模块,类似于以前的IIS版本中的ISAPI筛选器,它参与每个请求处理.IIS中一些现成的模块包括身份验证模块(用于处理请求的身份验证状态),压缩模块(用于压缩返 ...

  4. centos 开启关闭网卡

    ifdown ifcfg-enp7s0 关闭网卡 ifup ifcfg-enp7s0 开启网卡

  5. C++ remove remove_if erase

    #include <iostream>#include <algorithm>#include <list>#include <vector>#incl ...

  6. 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_12.RabbitMQ研究-工作模式-统配符工作模式测试

    路由模式: 1.每个消费者监听自己的队列,并且设置带统配符的routingkey. 2.生产者将消息发给broker,由交换机根据routingkey来转发消息到指定的队列. 创建测试用例 交换机的名 ...

  7. Qt编写自定义控件24-图片轮播控件

    一.前言 上一篇文章写的广告轮播控件,采用的传统widget堆积设置样式表做的,这次必须要用到更高级的QPainter来绘制了,这个才是最高效的办法,本控件参考雨田哥的轮播控件,经过大规模的改造而成, ...

  8. uni-app 时间格式问题 new Date(str) IOS系统跟Android系统不兼容

    今天做了一个需求,要在列表中把后台返回来的时间给显示出来,使用 new Date(str)  在微信开发者工具上显示是没有问题的,然后在IOS系统上显示是NAN. 原因是 IOS系统只识别 " ...

  9. Python3 继承

    继承的好处:子类实现父类的全部功能 1.单继承 若父类和子类有共同的方法或属性,则子类对父类方法或属性进行覆盖 class ClassA: def __init__(self): self.a = ' ...

  10. 阿里开源支持缓存线程池的ThreadLocal Transmittable ThreadLocal(TTL)

    功能 在使用线程池等会缓存线程的组件情况下,提供ThreadLocal值的传递功能. JDK的InheritableThreadLocal类可以完成父子线程值的传递. 但对于使用线程池等会缓存线程的组 ...