zoukankan      html  css  js  c++  java
  • Django之URL(路由系统)用法

    路由系统

    路由系统概念

    简而言之,路由系统就是路径和视图函数的一个对应关系。
    django的路由系统作用就是使views里面处理数据的函数与请求的url建立映射关系。使请求到来之后,根据urls.py里的关系条目,去查找到与请求对应的处理方法,从而返回给客户
    端http页面数据

    路由系统的格式

    url(正则表达式,view视图函数/视图类,参数)

    django 项目中的url规则定义放在project 的urls.py目录下,
    默认如下:

    from django.conf.urls import url
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
    ]

    url()函数可以传递4个参数,其中2个是必须的:regex和view,以及2个可选的参数:kwargs和name。下面是具体的解释:

    • regex:
      regex是正则表达式的通用缩写,它是一种匹配字符串或url地址的语法。Django拿着用户请求的url地址,在urls.py文件中对urlpatterns列表中的每一项条目从头开始进行逐一对比,
      一旦遇到匹配项,立即执行该条目映射的视图函数或二级路由,其后的条目将不再继续匹配。因此,url路由的编写顺序至关重要!

    需要注意的是,regex不会去匹配GET或POST参数或域名,例如对于https://www.example.com/myapp/,regex只尝试匹配myapp/。对于https://www.example.com/myapp/?page=3,regex也只尝试匹配myapp/。

    如果你想深入研究正则表达式,可以读一些相关的书籍或专论,但是在Django的实践中,你不需要多高深的正则表达式知识。

    性能注释:正则表达式会进行预先编译当URLconf模块加载的时候,因此它的匹配搜索速度非常快,你通常感觉不到。

    • view:

      当正则表达式匹配到某个条目时,自动将封装的HttpRequest对象作为第一个参数,正则表达式“捕获”到的值作为第二个参数,传递给该条目指定的视图。如果是简单捕获,那么捕获值将作
      为一个位置参数进行传递,如果是命名捕获,那么将作为关键字参数进行传递。
    • kwargs:

      任意数量的关键字参数可以作为一个字典传递给目标视图。
    • name:

      对你的URL进行命名,可以让你能够在Django的任意处,尤其是模板内显式地引用它。相当于给URL取了个全局变量名,你只需要修改这个全局变量的值,在整个Django中引用它的地方也将
      同样获得改变。这是极为古老、朴素和有用的设计思想,而且这种思想无处不在。

    1.最基础映射

    用户访问http://127.0.0.1:8000/index 然后后端使用index()函数处理(简单来说就是硬性匹配,写的什么就去匹配什么,没有一点回旋余地)

    urls.py
    
    from django.conf.urls import include, url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/$', views.index),
      ]

    1、先从创建的app下的views.py面定义处理数据的函数

    2、在urls.py里导入views

    3、在urlpatterns里写入一条url与处理函数的l映射关系

    4、url映射一般是一条正则表达式,“^” 字符串的开始,“$“ 字符串的结束

    5、当写成^$不输入任何url时不会在返回黄页,而是返回后面函数里对应的页面。一般这一条会写在url的最后。如

    2.按照顺序放置的动态路由

    可以使用正则来匹配URL,将一组url使用一条映射搞定

    urlpatterns = [
         url(r'^host/(d+)$', views.host),
         url(r'^host_list/(d+)/(d+)$', views.host_list), 
    ]

    ^host/(d+)$
    相对应的url是: ”http://127.0.0.1/host/2“ (d+)是匹配任意的数字,在分页时灵活运用。
    在views.host中需要指定一个形式参数来接受(d+)$ 的值

     def user_list(request,id):
         return HttpResponse(id)

    ^host_list/(d+)/(d+)$

    相对应的url是: ”http://127.0.0.1/host/8/9“,匹配到的数字会以参数的形式按照顺序传递给views里面相对应的函数
    在views.host_list中需要指定两个形式参数,注意:此参数的顺序严格按照url中匹配的顺序

     def user_list(request,hid,hid2): 
         return HttpResponse(hid+hid2)

    3.传参形势的路由

    利用正则表达式的分组方法,将url以参数的形式传递到函数,可以不按顺序排列

    urlpatterns = [ 
         url(r'^user_list/(?P<v1>d+)/(?P<v2>d+)$',views.user_list), 
     ]
    (?P<v1>d+)
    
    正则表达式的分组,相当于一个字典, key=v1, value=d+。 {"v1":"d+"}

    然后将此参数传递到views里对应的函数,可以不按照顺序

    def user_list(request,v2,v1):
     
         return HttpResponse(v1+v2)
    参数v1 = (?P<v1>d+)
    
    参数v2 = (?P<v2>d+)

    4.根据不同的app来分发不同的url(include方法)

    如果一个项目下有很多的app,那么在urls.py里面就要写巨多的urls映射关系。这样看起来很不灵活,而且杂乱无章。
    我们可以根据不同的app来分类不同的url请求。
    首先,在urls.py里写入urls映射条目。注意要导入include方法

    from django.conf.urls import include, url
    from django.contrib import admin
    from app01 import app01_urls
    from app02 import app02_urls
    urlpatterns = [ url(r'^app01/', include('app01.urls')), url(r'^app02/', include('app02.urls')), ]

    这条关系的意思是将url为”app01/“的请求都交给app01下的urls去处理

    其次,在app01下创建一个urls.py文件,用来处理请求的url,使之与views建立映射

    from django.conf.urls import include, url
    from app01 import views
    
    urlpatterns = [
    
        url(r'index/$', views.index),
    
    ]

    想对于url请求为: "http://127.0.0.1/app01/index/"

    5.通过反射机制,为django开发一套动态的路由系统

    在urls.py里定义分类正则表达式

    from django.conf.urls import patterns, include, url
    from django.contrib import admin
    from DynamicRouter.activator import process
    
    urlpatterns = patterns('',
        # Examples:
        # url(r'^$', 'DynamicRouter.views.home', name='home'),
        # url(r'^blog/', include('blog.urls')),
    
        url(r'^admin/', include(admin.site.urls)),
        
        
        ('^(?P<app>(w+))/(?P<function>(w+))/(?P<page>(d+))/(?P<id>(d+))/$',process),
        ('^(?P<app>(w+))/(?P<function>(w+))/(?P<id>(d+))/$',process),
        ('^(?P<app>(w+))/(?P<function>(w+))/$',process),
        ('^(?P<app>(w+))/$',process,{'function':'index'}),
    )

    在同目录下创建activater.py

    from django.shortcuts import render_to_response,HttpResponse,redirect
    
    
    def process(request,**kwargs):
        '''接收所有匹配url的请求,根据请求url中的参数,通过反射动态指定view中的方法'''
        
        app =  kwargs.get('app',None)
        function = kwargs.get('function',None)
        
        try:
            appObj = __import__("%s.views" %app)
            viewObj = getattr(appObj, 'views')
            funcObj = getattr(viewObj, function)
            
            #执行view.py中的函数,并获取其返回值
            result = funcObj(request,kwargs)
            
        except (ImportError,AttributeError),e:
            #导入失败时,自定义404错误
            return HttpResponse('404 Not Found')
        except Exception,e:
            #代码执行异常时,自动跳转到指定页面
            return redirect('/app01/index/')
        
        return result

    6.FBV和CBV

    所谓FBV和CBV 是指url 和view的对应关系

    FBV function base view /url/ --> 函数
    CBV class base view /url/ -->类

    上述都是FBV的方式。下面对CBV进行说明:

    • urls.py
    url(r'^cbv',views.CBVtest.as_view()),
    • views.py
    class CBVtest(View):
        def dispatch(self, request, *args, **kwargs):
            print("类似装饰器:before")
            result = super(CBVtest, self).dispatch(request, *args, **kwargs)
            print("类似装饰器:after")
            return result
    
        def get(self, request):  # 定义get方法,get请求执行这个方法
            print(request.method)
            return HttpResponse('cbvget')
    
        def post(self, request):  # 定义post方法,post请求执行这个方法
            print(request.method)
            return HttpResponse('cbvpost')

     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。

    反相解析定义

    随着功能的增加会出现更多的视图,可能之前配置的正则表达式不够准确,于是就要修改正则表达式,但是正则表达式一旦修改了,之前所有对应的超链接都要修改,真是一件麻烦的事情,而且可能还会漏掉一些超链接忘记修改,有办法让链接根据正则表达式动态生成吗? 就是用反向解析的办法

    应用范围

    模板中的超链接
    视图中的重定向

    使用方法

    namespace和name属性

    定义url时,需要为include定义namespace属性,为url定义name属性
    使用时,在模板中使用url标签,在视图中使用reverse函数,根据正则表达式动态生成地址,减轻后期维护成本。

    模板中超链接步骤

    1)在项目urls.py中为include定义namespace属性。

    url(r’^’,include(‘booktest.urls’,namespace=’booktest’)),

    2)在应用的urls.py中为url定义name属性,并修改为fan2。

    url(r’^fan2/$’, views.fan2,name=’fan2’),

    3)在模板中使用url标签做超链接,此处为templates/booktest/fan1.html文件。

    <html>
    <head>
        <title>反向解析</title>
    </head>
    <body>
    普通链接:<a href="/fan2/">普通fan2</a>
    <hr>
    反向解析:<a href="{%url 'booktest:fan2'%}">反向解析fan2</a>
    </body>
    </html>

    4)回到浏览器中,后退,刷新,查看源文件,两个链接地址一样。

    这里写图片描述

    5)在应用的urls.py中,将fan2修改为fan_show。

    url(r’^fan_show/$’, views.fan2,name=’fan2’),

    6)回到浏览器中,刷新,查看源文件,两个链接地址不一样。

    这里写图片描述

    视图中的重定向

    from django.shortcuts import redirect
    from django.core.urlresolvers import reverse
    
    return redirect(reverse('booktest:fan2'))

    反向解析中URL的参数

    位置参数

    1)在booktest/urls.py中,修改fan2如下:

    url(r’^fan(d+)_(d+)/$’, views.fan2,name=’fan2’),

    2)修改templates/booktest/fan1.html文件如下:

    <html>
    <head>
        <title>反向解析</title>
    </head>
    <body>
    普通链接:<a href="/fan2_3/">fan2</a>
    <hr>
    反向解析:<a href="{%url 'booktest:fan2' 2 3%}">fan2</a>
    </body>
    </html>

    3)回到浏览器中,刷新,查看源文件如下图:

    这里写图片描述

    • 使用重定向传递位置参数格式如下:

    return redirect(reverse(‘booktest:fan’, args=(2,3)))

    关键字参数

    1)在booktest/urls.py中,修改fan2如下:

     url(r'^fan(?P<id>d+)_(?P<age>d+)/$', views.fan2,name='fan2'),

    2)修改templates/booktest/fan1.html文件如下:

    <html>
    <head>
        <title>反向解析</title>
    </head>
    <body>
    普通链接:<a href="/fan100_18/">fan2</a>
    <hr>
    反向解析:<a href="{%url 'booktest:fan2' id=100 age=18%}">fan2</a>
    </body>
    </html>

    3)回到浏览器中,刷新,查看源文件如下图:

    这里写图片描述

    • 使用重定向传递关键字参数格式如下:

    return redirect(reverse(‘booktest:fan2’, kwargs={‘id’:110,’age’:26}))

     

  • 相关阅读:
    C++学习9 this指针详解
    福建省第八届 Triangles
    UVA 11584 Partitioning by Palindromes
    POJ 2752 Seek the Name, Seek the Fame
    UVA 11437 Triangle Fun
    UVA 11488 Hyper Prefix Sets (字典树)
    HDU 2988 Dark roads(kruskal模板题)
    HDU 1385 Minimum Transport Cost
    HDU 2112 HDU Today
    HDU 1548 A strange lift(最短路&&bfs)
  • 原文地址:https://www.cnblogs.com/bypp/p/7992933.html
Copyright © 2011-2022 走看看