• 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}))

     

  • 相关阅读:
    Atitit sumdoc t5 final file list \sumdoc t5 final\sumdoc t511 \sumdoc t5 final\sumdoc t511.zip \sum
    上课流程法如何上好第一节课(1) 目录 1. 目录 1 1.1. 销售自己 1 1.2. 销售课程 1 1.3. 学习方法 1 1.4. 制定规章 2 2. 销售自己自我介绍 2 2.1.
    Atitit 重复文件清理工具 按照文件名 目录 1. 原理, 1 1.1. If base filex exist dele other files 1 1.2. Get getStartIdex
    Atitit sumdoc index 2019 v6 t56 .docx Atitit sumdoc index s99 目录 1. Zip ver 1 1.1. C:\Users\Adminis
    Atitit lucence es solr的各种query 与sql运算符的对比 目录 1.1. 等于运算 TermQuery 1 1.2. 范围运算 1 1.3. 大小运算 1 1.4. Wi
    Atitit 程序设计概论 艾提拉著作 目录 1. 界面ui设计 1 2. 编程语言部分 1 3. 面向对象的程序设计 1 4. 算法章节 数据结构 1 5. 第21章 标准库 2 5.1. 文件i
    Atitit 命令行执行sql 跨语言 目录 1.1. 无需输入密码,那就不要p参数即可 1 1.2. 4.使用mysql命令执行 1 1.3. 5.mysql命令执行sql,并将查询结果保存到
    Atitit java播放 wav MIXER 混响器编程 目录 1.1. MIXER 混响器编程 1 1.2. 得到系统中一共有多少个混音器设备: 1 1.3. 接口摘要 1 1.4. 调节音量
    Atitit object 和class的理解 目录 1.1. 发现很多Object的方法都是相同的,他们被重复地放在一个个对象当中,太浪费了。 1 1.2. 那我们怎么把这些Object给创建起来
    Atitit 数据库的历史与未来 目录 1.1. 两个对于数据库强需求的行业。电信 金融 1 1.2. 艾提拉分析 对数据库强需求行业金融 1 2. 数据库历史 2 2.1. ,上个世纪50,6
  • 原文地址:https://www.cnblogs.com/bypp/p/7992933.html
Copyright © 2020-2023  润新知