资讯专栏INFORMATION COLUMN

Django-02.url、错误处理以及命名空间

KaltZK / 3134人阅读

摘要:第二种方式叫做反向解析反向匹配反向查询或者简单的反查。一个命名空间有两个部分,它们都是字符串应用命名空间它表示正在部署的应用的名称。例如,可以预见的管理站点的应用命名空间是。的命名空间使用操作符指定。

1.Django 如何处理一个请求

Django 决定要使用的根URLconf 模块。通常,这个值就是ROOT_URLCONF 的设置,但是如果进来的HttpRequest对象具有一个urlconf 属性(通过中间件request processing 设置),则使用这个值来替换ROOT_URLCONF设置。

Django 加载该Python 模块并寻找可用的urlpatterns。它是django.conf.urls.url()
实例的一个Python 列表。

Django 依次匹配每个URL 模式,在与请求的URL 匹配的第一个模式停下来。 一旦其中的一个正则表达式匹配上,Django将导入并调用给出的视图,它是一个简单的Python 函数(或者一个基于类的视图)。视图将获得如下参数: 一个HttpRequest 实例。

如果匹配的正则表达式返回了没有命名的组,那么正则表达式匹配的内容将作为位置参数提供给视图。关键字参数由正则表达式匹配的命名组组成,但是可以被django.conf.urls.url()的可选参数kwargs覆盖。

如果没有匹配到正则表达式,或者如果过程中抛出一个异常,Django 将调用一个适当的错误处理视图。

2.URL解释:

schema://host[:port#]/path/.../?query-string

schema:指定使用的协议(例如:http, https, ftp)

host:Http服务器的IP地址或者域名

port:端口号,默认是80端口

path:访问资源的路径

query-string:发送给http服务器的数据

anchor:锚点

3.URL中的正则
url(r"^test1/9999/$", views.test1.as_view()),                #普通用法
url(r"^test2/([0-9]{4})/$", views.test2.as_view()),        # 单个非命名参数
url(r"^test3/([0-9]{4})/([0-9]{2})/$", views.test3.as_view()),
url(r"^test4/([0-9]{4})/([0-9]{2})/([0-9]+)/$", views.test4.as_view()),

我们先开始建一个django工程 在这里我们给给工程命名为lesson1 放在Django_lesson文件夹下
具体建django工程的细节详情见Django-01、初识Django和搭建Django helloworld

然后新建一个app 名为urltest

在lesson1.url.py 中导入view

from urltest import views
4.非命名参数

在lesson.urls.py中添加以下路由

    url(r"^admin/", admin.site.urls),
    url(r"^test1/9999/$", views.Test1.as_view()),
    url(r"^test2/([0-9]{4})/$", views.Test2.as_view()),
    url(r"^test3/([0-9]{4})/([0-9]{2})/$", views.Test3.as_view()), views.Test4.as_view()),

在urltest.view.py中添加以下视图类

class Test1(View):
    def get(self, request):
        msg = "Test1 sucessful"
        return HttpResponse(msg)


class Test2(View):
    def get(self, request, year):
        msg = "Test2 sucessful  %s 年" % year
        return HttpResponse(msg)


class Test3(View):
    def get(self, request, year, month):
        msg = "Test3 sucessful %s 年 %s 月" % (year, month)
        return HttpResponse(msg)

注:
若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
每个正则表达式前面的"r" 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义。参见Dive Into Python 中的解释。

^代表开始匹配,如果只有^符号,则只需要部分匹配成功即可
$代表结束匹配,添加$符号, 一般就代表完整匹配

我们的URL匹配规则一定需要保持唯一

5.命名参数

上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL 中的值并以位置 参数传递给视图。在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。
在Python 正则表达式中,命名正则表达式组的语法是(?Ppattern),其中name 是组的名称,pattern 是要匹配的模式。

    url(r"^test4/(?P[0-9]{4})/$", views.Test4.as_view()),
    url(r"^test5/(?P[0-9]{4})/(?P[0-9]{2})/$", views.Test5.as_view()),

在urltest.view.py中添加以下视图类

class Test4(View):
    def get(self, request, year):
        msg = "Test3 sucessful %s 年" % year
        return HttpResponse(msg)


class Test5(View):
    def get(self, request, month, year):  # 这里我们交换了year和month的顺序
        msg = "Test3 sucessful %s 年 %s 月" % (year, month)
        return HttpResponse(msg)






如果有命名参数,则使用这些命名参数,忽略非命名参数。
否则,它将以位置参数传递所有的非命名参数。
请求的URL被看做是一个普通的Python 字符串, URLconf在其上查找并匹配。进行匹配时将不包括GET或POST请求方式的参数以及域名。换句话讲,所有的请求方法 —— 即,对同一个URL的无论是POST请求、GET请求、或HEAD请求方法等等 —— 都将路由到相同的函数。
每个捕获的参数都作为一个普通的Python 字符串传递给视图,无论正则表达式使用的是什么匹配方式。

包含其它的URLconfs

在任何时候,你的urlpatterns 都可以包含其它URLconf 模块。这实际上将一部分URL 放置于其它URL 下面。
在lesson1.urls.py中加入以下代码

    from django.conf.urls import include  # 导入 include
    url(r"^test7/", include("urltest.urls")),  # 加入路由

在urltest文件夹下新建urls.py加入以下代码

from django.conf.urls import url
from urltest import views
urlpatterns = [
    url(r"^test7/$", views.Test7.as_view()),
]

在urltest.views.py加入以下视图类

class Test7(View):
    def get(self, request):  # 这里我们交换了year和month的顺序
        msg = "Test7 sucessful"
        return HttpResponse(msg)
传递额外的选项给视图函数

URLconfs 具有一个钩子,让你传递一个Python 字典作为额外的参数传递给视图函数。
django.conf.urls.url() 函数可以接收一个可选的第三个参数,它是一个字典,表示想要传递给视图函数的额外关键字参数。

#lesson1.urls.py中加入这个路由
url(r"^test8/", include("urltest.urls"), {"name": "lethe", "date": "2018"}),

#urltest.urls.py中加入这个路由
url(r"^test8/$", views.Test8.as_view()),

#views.py中加入这个视图类
class Test8(View):
    def get(self, request, name, date):  # 这里我们交换了year和month的顺序
        msg = "Test8 sucessful by %s in %s" % (name, date)
        return HttpResponse(msg)

6.错误处理

当Django 找不到一个匹配请求的URL 的正则表达式时,或者当抛出一个异常时,Django 将调用一个错误处理视图。

Http状态码
每一个请求,都会返回一个状态
200 : 请求正常
404:找不到页面
403:是指服务器拒绝
400:request异常
500:服务器异常

在URLconf中指定参数,这些参数分别是

handler404
一个callable或一个字符串,表示如果没有URL模式匹配,应该调用的视图的完整Python导入路径。
默认情况下是"django.views.defaults.page_not_found"。

handler500
一个callable或一个字符串,表示如果没有URL模式匹配,应该调用的视图的完整Python导入路径。
默认情况下,这是"django.views.defaults.page_not_found"。

handler403
一个callable或一个字符串,表示如果用户没有访问资源所需的权限,应调用的视图的完整Python导入路径。
默认情况下,这是"django.views.defaults.permission_denied"。

handler400
如果HTTP客户端已发送导致错误条件的请求和状态代码为400的响应,则应调用的可调用或表示完整的Python视图导入路径的字符串。
默认情况下,这是"django.views.defaults.bad_request"。

在settings.py中将DEBUG值改为True
当找不到页面的时候 页面显示如下图

然后我们再在settings.py中将DEBUG值改为False (我们一般在开发的时候设置DEBUG值为True 在产品上线的时候将DEBUG值改为False)
当找不到页面的时候 页面显示如下图

我们将代码作如下更改

#在views.py中加入以下代码
def Error404(request):
    return HttpResponse("哎呦 404 尴尬了!")

#DEBUG值保持为False
#在lesson1.py中加入
handler404 = "urltest.views.Error404"   

7.URL 的反向解析

在使用Django 项目时,一个常见的需求是获得URL 的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。
人们强烈希望不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 毫不相关的专门的URL 生成机制,因为这样容易导致一定程度上产生过期的URL。
换句话讲,需要的是一个DRY 机制。除了其它优点,它还允许设计的URL 可以自动更新而不用遍历项目的源代码来搜索并替换过期的URL。
要获取一个URL,最初拥有的信息是负责处理它的视图的标识(例如名字),与查找正确的URL 的其它必要的信息如视图参数的类型(位置参数、关键字参数)和值。
Django 提供了一个解决方案使得URL 映射是URL 设计唯一的储存库。你用你的URLconf填充它,然后可以双向使用它:
根据用户/浏览器发起的URL 请求,它调用正确的Django 视图,并从URL 中提取它的参数需要的值。
根据Django 视图的标识和将要传递给它的参数的值,获取与之关联的URL。
第一种方式是我们在前面的章节中一直讨论的用法。第二种方式叫做反向解析URL、反向URL匹配、反向URL查询或者简单的URL反查。
在需要URL 的地方,对于不同层级,Django 提供不同的工具用于URL 反查:
在模板中:使用url 模板标签。
在Python 代码中:使用django.core.urlresolvers.reverse() 函数。
在更高层的与处理Django 模型实例相关的代码中:使用get_absolute_url() 方法。

    #在urls.views.py中加入以下代码
    url(r"^articles/$", views.Articles.as_view()),
    #在views.py中加入以下代码
    class Articles(View):
    def get(self, request):
        return redirect("/test1/9999/")

7.URL 命名空间

URL 命名空间允许你反查到唯一的命名URL 模式,即使不同的应用使用相同的URL 名称。第三方应用始终使用带命名空间的URL 是一个很好的实践(我们在教程中也是这么做的)。类似地,它还允许你在一个应用有多个实例部署的情况下反查URL。换句话讲,因为一个应用的多个实例共享相同的命名URL,命名空间提供了一种区分这些命名URL 的方法。

一个URL命名空间有两个部分,它们都是字符串:
应用命名空间
它表示正在部署的应用的名称。一个应用的每个实例具有相同的应用命名空间。例如,可以预见Django 的管理站点的应用命名空间是"admin"。
实例命名空间
它表示应用的一个特定的实例。实例的命名空间在你的全部项目中应该是唯一的。但是,一个实例的命名空间可以和应用的命名空间相同。它用于表示一个应用的默认实例。
URL 的命名空间使用":" 操作符指定。例如,管理站点应用的主页使用"admin:index"。它表示"admin" 的一个命名空间和"index" 的一个命名URL。
命名空间也可以嵌套。命名URL"sports:polls:index" 将在命名空间"polls"中查找"index",而poll 定义在顶层的命名空间"sports" 中。

    #在lesson1.urls.py中加入以下路由
    url(r"^url1test/", include("urltest.urls_1", namespace="url1test")),
    url(r"^url2test/", include("urltest.urls", namespace="url2test")),
    url(r"^url1_login/$", views.ToUrl1Login.as_view()),
    url(r"^url2_login/$", views.ToUrl2Login.as_view()),
    
    #在urltest文件夹下新建url_1.py并加入以下代码
    from django.conf.urls import url
    from urltest import views
    urlpatterns = [
    url(r"^login/$", views.Url1Login.as_view(), name="login"),
]

    #在urltest.url.py中加入以下路由
    url(r"^login/$", views.Url2Login.as_view(), name="login"),
    
    # 在views.py中加入以下视图类
    class Url1Login(View):
    def get(self, request):
        return HttpResponse("我是url1test.login")


class Url2Login(View):
    def get(self, request):
        return HttpResponse("我是url2test.login")


class ToUrl1Login(View):
    def get(self, request):
        return redirect(reverse("url1test:login"))


class ToUrl2Login(View):
    def get(self, request):
        return redirect(reverse("url2test:login"))

当输入/url1_login/时 跳到ToUrl1Login然后跳到url1test:login(即namespace="url1test",name="login"的路由 即/url1test/login/ 打印我是url1test.login)


8.附录 本文章代码: view.py
    # -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render
from django.views import View
from django.http import HttpResponse
from django.shortcuts import reverse, redirect
# Create your views here.


class Test1(View):
    def get(self, request):
        msg = "Test1 sucessful"
        return HttpResponse(msg)


class Test2(View):
    def get(self, request, year):
        msg = "Test2 sucessful  %s 年" % year
        return HttpResponse(msg)


class Test3(View):
    def get(self, request, year, month):
        msg = "Test3 sucessful %s 年 %s 月" % (year, month)
        return HttpResponse(msg)


class Test4(View):
    def get(self, request, year):
        msg = "Test4 sucessful %s 年" % year
        return HttpResponse(msg)


class Test5(View):
    def get(self, request, month, year):  # 这里我们交换了year和month的顺序
        msg = "Test5 sucessful %s 年 %s 月" % (year, month)
        return HttpResponse(msg)


class Test6(View):
    def get(self, request, num="1"):  # 这里我们交换了year和month的顺序
        msg = "Test6 sucessful num=%s" % num
        return HttpResponse(msg)


class Test7(View):
    def get(self, request):  # 这里我们交换了year和month的顺序
        msg = "Test7 sucessful"
        return HttpResponse(msg)


class Test8(View):
    def get(self, request, name, date):  # 这里我们交换了year和month的顺序
        msg = "Test8 sucessful by %s in %s" % (name, date)
        return HttpResponse(msg)


class Articles(View):
    def get(self, request):
        return redirect("/test1/9999/")

class Reverse_test(View):
    def get(self, request):
        return redirect(reverse("reverse_test", args=("2021",)))


class Url1Login(View):
    def get(self, request):
        return HttpResponse("我是url1test.login")


class Url2Login(View):
    def get(self, request):
        return HttpResponse("我是url2test.login")


class ToUrl1Login(View):
    def get(self, request):
        return redirect(reverse("url1test:login"))


class ToUrl2Login(View):
    def get(self, request):
        return redirect(reverse("url2test:login"))

def Error404(request):
    return HttpResponse("哎呦 404 尴尬了!")
lesson1.urls.py
from django.conf.urls import url, include
from django.contrib import admin
from urltest import views

urlpatterns = [
    url(r"^admin/", admin.site.urls),
    url(r"^test1/9999/$", views.Test1.as_view()),
    url(r"^test2/([0-9]{4})/$", views.Test2.as_view(), name="reverse_test"),
    url(r"^test3/([0-9]{4})/([0-9]{2})/$", views.Test3.as_view()),
    url(r"^test4/(?P[0-9]{4})/$", views.Test4.as_view()),
    url(r"^test5/(?P[0-9]{4})/(?P[0-9]{2})/$", views.Test5.as_view()),
    url(r"^test6/(?P[0-9]+)/$", views.Test6.as_view()),
    url(r"^test7/", include("urltest.urls")),
    url(r"^test8/", include("urltest.urls"), {"name": "lethe", "date": "2018"}),
    url(r"^articles/$", views.Articles.as_view()),
    url(r"^reverse/$", views.Reverse_test.as_view()),

    url(r"^url1test/", include("urltest.urls_1", namespace="url1test")),
    url(r"^url2test/", include("urltest.urls", namespace="url2test")),
    url(r"^url1_login/$", views.ToUrl1Login.as_view()),
    url(r"^url2_login/$", views.ToUrl2Login.as_view()),

]

handler404 = "urltest.views.Error404"
urltest.urls.py
from django.conf.urls import url
from urltest import views
urlpatterns = [
    url(r"^test7/$", views.Test7.as_view()),
    url(r"^test8/$", views.Test8.as_view()),
    url(r"^login/$", views.Url2Login.as_view(), name="login"),
]
urls_1.py
from django.conf.urls import url
from urltest import views
urlpatterns = [
    url(r"^login/$", views.Url1Login.as_view(), name="login"),
]
目录结构

注: 本文章是本人的CSDN博客中对应的文章转过来的

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41462.html

相关文章

  • SOAP 介绍

    摘要:此协议规范由和在年共同提出,并得到,莲花,康柏等公司的支持,于年提交给万维网联盟。现在,协议规范由万维网联盟的工作组维护。然而,在上使用并不仅限于协议绑定。元素用于在消息中传输错误及状态信息。 简介 SOAP(Simple Object Access Protoco)简单对象访问协议是在分散或分布式的环境中交换信息的简单的协议,是一个基于 XML 的协议。此协议规范由 IBM、Micr...

    kgbook 评论0 收藏0
  • 高程3总结#第18章JavaScript与XML

    摘要:在基于使用命名空间的文档求值时,需要使用对象。第四个参数的取值类型是下列常量之一,返回与表达式匹配的数据类型。,返回字符串值。这是最常用的结果类型。集合中节点的次序与它们在文档中的次序一致。 JavaScript与XML 浏览器对XML DOM的支持 DOM2级核心 在通过JavaScript处理XML时,通常只使用参数root,因为这个参数指定的是XML DOM文档元素的标签名 v...

    gaosboy 评论0 收藏0
  • 猫头鹰的深夜翻译:从1000+JS项目中汇总的10个最容易出现的错误(以及如何解决)

    摘要:常出现的错误前十位为了可读性,错误名称进行了一定的简写。让我们深入了解每个错误发生的原因以及解决方法。这个问题很容易解决。当未捕获的错误跨越违法跨域策略的域边界时,会发生脚本错误。这是当你在中试图调用的方法时出现的错误。 JavaScript常出现的错误前十位 showImg(https://segmentfault.com/img/bV3Z1z?w=1116&h=691); 为了可读...

    eccozhou 评论0 收藏0
  • PHP use类文件中的命名空间问题解析

    摘要:但实际上在命名空间这里却不一样,不同类文件中的命名空间之间是相互分离的,即某个文件中定义的的命名空间,在其他的类文件中不能使用。解决在中添加依赖类库的命名空间别名以上就是今天遇到的关于命名空间的一个坑,谨记于此。 (没想好title,见谅) 导读 PHP的类文件在被其他文件include的时候不能直接使用其他文件中的已定义的别名。比如有三个文件。 test.php 一个简单的脚...

    Zack 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<