zoukankan      html  css  js  c++  java
  • Django url处理

    Django如何处理一个请求
    当一个用户请求Django 站点的一个页面,下面是Django 系统决定执行哪个Python 代码遵循的算法:
    1:Django 决定要使用的根URLconf 模块。通常,这个值就是ROOT_URLCONF 的设置,但是如果进来的HttpRequest 对象具有一个urlconf 属性
    (通过中间件request processing 设置),则使用这个值来替换ROOT_URLCONF 设置。
    2:Django 加载该Python 模块并寻找可用的urlpatterns。它是django.conf.urls.url() 实例的一个Python 列表。
    3:Django 依次匹配每个URL 模式,在与请求的URL 匹配的第一个模式停下来。
    4:一旦其中的一个正则表达式匹配上,Django 将导入并调用给出的视图,它是一个简单的Python 函数(或者一个基于类的视图)。视图将获得如下参数:

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

    5:如果没有匹配到正则表达式,或者如果过程中抛出一个异常,Django 将调用一个适当的错误处理视图。
    比如handler404,handler500,handler403。我们也可以自定义对应的错误视图覆盖提供的默认错误处理视图。
    代码浅析:

    ##/Python34/Lib/site-packages/django/core/handlers/base.py
        def _get_response(self, request):
            """
            Resolve and call the view, then apply view, exception, and
            template_response middleware. This method is everything that happens
            inside the request/response middleware.
            """
            #解析并调用视图函数,并应用视图、异常和模板中间件 
            response = None
    
            if hasattr(request, 'urlconf'):  #如果进来的HttpRequest 对象具有一个urlconf 属性,则进行替换
                urlconf = request.urlconf
                set_urlconf(urlconf)  #这个函数里面进行urlconf的替换
                resolver = get_resolver(urlconf) #获得RegexURLResolver对象(URL分解器)
            else:
                resolver = get_resolver() 
    
            resolver_match = resolver.resolve(request.path_info) #启动匹配,在这里面就在url_pattrns中进行匹配:
                                                                 #返回resolver_match实例
            callback, callback_args, callback_kwargs = resolver_match
            request.resolver_match = resolver_match
    
            # Apply view middleware  应用视图应用层
            for middleware_method in self._view_middleware:
                response = middleware_method(request, callback, callback_args, callback_kwargs)
                if response:         #获得响应则跳出循环
                    break
    
            if response is None:     #
                wrapped_callback = self.make_view_atomic(callback)
                try:
                    response = wrapped_callback(request, *callback_args, **callback_kwargs)
                except Exception as e:
                    response = self.process_exception_by_middleware(e, request)
    
            # Complain if the view returned None (a common error).
            if response is None:    #响应是空
                if isinstance(callback, types.FunctionType):    # FBV
                    view_name = callback.__name__
                else:                                           # CBV
                    view_name = callback.__class__.__name__ + '.__call__'
    
                raise ValueError(
                    "The view %s.%s didn't return an HttpResponse object. It "
                    "returned None instead." % (callback.__module__, view_name)
                )
    
            # If the response supports deferred rendering, apply template
            # response middleware and then render the response
            # 如果支持延迟渲染,则应用模板进行渲染,使用render函数,最后返回response
            elif hasattr(response, 'render') and callable(response.render):
                for middleware_method in self._template_response_middleware:
                    response = middleware_method(request, response)
                    # Complain if the template response middleware returned None (a common error).
                    if response is None:
                        raise ValueError(
                            "%s.process_template_response didn't return an "
                            "HttpResponse object. It returned None instead."
                            % (middleware_method.__self__.__class__.__name__)
                        )
    
                try:
                    response = response.render()
                except Exception as e:
                    response = self.process_exception_by_middleware(e, request)
    
            return response
    ##其中代码实现内容还是挺多的,后续会将流程整理出来重新写一篇博客

    命名组和非命名组
    举个例子:
    url(r'^articles/([0-9]{4})/$', views.year_archive) --> 没有命名的正则表达式
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive) --> 命名正则表达式
    在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name 是组的名称,pattern 是要匹配的模式。
    其实两者起到的作用是一样的,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数。
    这就意味这个你的URLconf会更加清晰且不容易产生参数顺序问题的错误。
    例如:/articles/2005/ 请求将调用views.month_archive(request, year='2005')函数,而不是views.month_archive(request, '2005')。

    包含其它的URLconfs
    1:include子模块的URLconf,进行匹配的时候,Django会去掉URL中匹配的部分并将剩下的字符串发送给包含的URLconf 做进一步处理
    例如:url(r'^polls/', include('polls.urls', namespace="polls"))
    2:使用一个url()实例的列表用于移除URL配置中重复的部分,例如:
    url(r'^polls/', include([
    url(r'^history/$', views.history),
    url(r'^permissions/$', views.permissions),
    url(r'^edit/$', views.edit),
    ])),
    这里个人感觉就是看起来代码清晰一点。

    URL 的反向解析
    反向解析就是通过Django视图的标识和将要传递给它的参数的值,获取与之关联的URL。
    这样就可以避免硬编码这些URL,这样后期要是URL发生改变,只要视图的标识没有改变,修改URLconf的内容不会有其他影响的
    在需要URL 的地方,对于不同层级,Django 提供不同的工具用于URL 反查:

    • 在模板中:使用url 模板标签。
    • 在Python 代码中:使用django.core.urlresolvers.reverse() 函数。
    • 在更高层的与处理Django 模型实例相关的代码中:使用get_absolute_url() 方法。

    例如:urlpatterns中是如此映射的:url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive')
    则在html中则可以这样反查:<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }}
    在Python代码中这样处理: return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

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

  • 相关阅读:
    HDU 5444 Elven Postman (2015 ACM/ICPC Asia Regional Changchun Online)
    POJ 1577 Falling Leaves 二叉搜索树
    HDU 3791 二叉搜索树
    Problem: Godfather 树的重心
    Problem: [Poi0202]Travelling Salesman 最近公共祖先
    Problem: 最优连通子集
    Problem: 扫雪系列II
    Problem: 扫雪系列I
    Problem: [Ural1039]没有上司的晚会
    Problem: 八中教室的灯
  • 原文地址:https://www.cnblogs.com/BGPYC/p/8025367.html
Copyright © 2011-2022 走看看