zoukankan      html  css  js  c++  java
  • Django学习笔记〇九——路由系统

    我们在前面讲了Django的第一个部分——视图系统,今天来看看第二个部分:路由系统。

    什么是路由系统?

     简而言之,Django的路由系统就是建立视图views里和请求的url之间的映射关系。在请求到来之后,根据urls.py中的关系条目,查找相应的处理方法,从而返回给用户所需要的html页面。

    最基础的映射关系

    我们前面的几个项目案例中,用到的都是这种最基础的映射关系:

    只有一个App

    只有一级路由

    路由里的url写的都是简单的正则表达式,通过这种简单的正则来获取一个不带参数的url

    看看前面的urls.py里的列表是怎么定义的

    from django.conf.urls import url,
    urlpatterns = [
        path('admin/', admin.site.urls),
        url('^mainpage/',views.mainpage),
        url('^publisher/',views.publisher),
        url('^add_publisher/',views.add_publisher),
        url('^edit_publisher/',views.edit_publisher),
        url('^delete_publisher/',views.delete_publisher),
        url('^add_book/',views.add_book),
        url('^edit_book/',views.edit_book),
        url('^test/',views.test)
    ]

    注意下这里的正则表达式,我们只用^符号定义了url的起始字符,有些时候还可以用$符号定义字符串的结尾,区别就是

    url('^test/',views.test)

    这个可以对以test/开始的url请求进行相应,包括带参数的:就像127.0.0.1:8000/test/?year=1这种的

    而限定结尾的只对这种指定的url进行相应,如果是二级的路由也不行:127.0.0.1:8000/tetst1/test2,这种url是不会相应的,但是用上面那个只限制开始的就可以。

    一个特殊的正则方法

    有的时候我们用省略开头和结尾之间的字符串来实现直接用127.0.0.1:8000来直接显示页面(一般是home页面)

    url(r'^$',views.home)
    包含include的路由系统(二级路由)

     我们前面只创建了一个app,和app/views.py里映射的urls.py是一级路由,如果有这么一种情况,我们创建了多个app,那么我们还可以在各个app路径下创建一个新的urls.py,那么这个urls.py里的映射关系就是一个二级的路由。二级路由在使用的时候需要在一级路由中指定一下,就要用到一个叫include的方法。假设我们创建了两个app,路径大概是这样的(这里只放出来了几个重要的py文件)

    |----app01
    |    |-urls.py
    |    |-__init__.py
    |    |-apps.py
    |    |-views.py
    |    
    |----app02
         |-urls.py
         |-__init__.py
         |-apps.py
         |-views.py

    一般情况下这两个app用于实现不同的功能。我们可以在各个app下的urls里指定对应的映射。那么在最外面的urls.py就是一级路由,而各个app里新建的urls.py里的映射就是二级路由,我们在使用二级路由的时候要用include的方法把二级路由的py文件导入一级路由

    from app01 import urls as urls_app01
    from app02 import urls as urls_app02
    
    urlpatterns = [
        url(r'^app01',include(urls_app01)),
        url(r'^app02',include(urls_app02))
    ]

    然后我们在app内的views里放好各自的映射效果就行了。注意我这里就是为了便于理解把app名字简单起了个app01和app02,真实项目中要起的名字要跟业务逻辑相符。

    路由中传递参数

    我们还可以在定义路由关系的时候传递一个“莫名其妙”的参数,这个参数是以字典的方式进行传递的

    url(r'^test/',views.test,{'name':'Jack'})

    然后在test这个函数中就可以拿到这个参数

    def test(request,name):
        print(name)
        return HttpResponse(12345)

    这种方法用环境非常少,只作为个了解就可以了。

    命名URL以及URL的反向解析

    模板中跳转

    有些时候有这样一种用法:两个界面是一家公司的,一个页面主要负责租房,另一个页面主要负责卖房子,在各自的页面上都有对方的“友情链接”,这个效果的实现是比较简单的,最简单暴力的方法就是在模板上直接放一个a标签

    <body>
        <h1>这是卖房子的首页</h1>
    
        <div>
            <p>友情链接</p>
            <a href="/rentinghouse/home">点击查看租房信息</a>
        </div>
    </body>
    
    另一个html文件
    <body>
        <h1>这是租房子的首页</h1>
    
        <div>
            <p>友情链接</p>
            <a href="/salehose/home">点击查看卖房信息</a>
        </div>
    </body>

    然后我们在url里只要设置好对应的映射就可以了,

    url(r'rentinghouse/',views.renting),
    url(r'salehouse/',vies.sale)

    这样写死url的方法叫硬编码。

    但是有个问题,万一我们需要对url进行调整,比方我们要把这个salehouse/改成salebuilding(只是这么个意思啊),那么我们并不知到这个salehouse在哪里是被用过的,这时候就要在最初的时候把他写成或的,给他起一个别名,然后用反向解析的方法来使用。

    urlpatterns = [
        url(r'^rentinghouse/',views.home,name='rentinghouse')
    ]

    然后我们在模板中可以直接使用这个‘别名’:rentinghouse

    <body>
        <h1>这是卖房的首页</h1>
    
        <div>
            <p>友情链接</p>
            <a href="{% url 'rentinghouse' %}">点击查看租房信息</a>
        </div>
    </body>

    在模板中就会用这个{% url 'rentinghouse' %}方法获取到指定的。那么以后不论在后期怎么更改路由里的url,都可以直接获取对应的页面。

    视图中跳转

    上面是在模板中进行跳转,我们也可以在视图中使用下面的方法来跳转

    def test(request):
        return redirect('/rentinghouse/')

    但是这里也是个硬编码,也是把url给写死了,所以也可以用反向解析的方法来操作

    from django.urls import reverse
    def test(request):
        redirect_url = reverse('rentinghouse')
        return redirect(redirect_url)

    要注意的是一旦上线一般情况url是不会在改变的,这里就是讲一下有这么一个方式可以使用。

    反向解析的本质就是给URL匹配模式起一个别名,然后通过别名来获取到具体的URL路径。

    带参数的路由映射

     我们前面在删除数据库的某个元素的时候用到的url是带参数的,类似这样的

    127.0.0.1:8000/deleteBook/?id=2
    127.0.0.1:8000、deletePubli/?id=3

    我们可以通过正则表达式用一个映射来满足两个url的效果

    url('^delete/([a-zA-Z]+)/(d+)$',views.delete)

    我们可以建立一个python文件试一试这个正则表达式的用法 

    import re
    r = re.compile(r'^delete/([a-zA-Z]+)/(d+)/$')
    
    ret = r.match('delete/author/10/')
    for i in ret.groups():
        print(i)
    
    
    ##########输出##########
    [Running] python3 -u "/home/qi/pro_code/test2.py"
    author
    10

    在正则表达的时候匹配的对象是一个字符串([a-zA-Z])还有一个数字(d+),如果匹配成功则(这里调用的是group,返回值是个元组)匹配出来的字符串会被作为位置参数传递给视图里的映射函数。

    我们可以用下面的方法来试一下传递的函数是怎么样的

    def delete(request,*args,**kwargs):
        print(args)
        return HttpResponse(12345)

    然后访问一下下面的URL:http://127.0.0.1:8000/delete/publisher/12345/,看看能打印出来什么东西:

    ('publisher', '12345')
    [02/Apr/2020 14:49:02] "GET /delete/publisher/12345/ HTTP/1.1" 200 5

    明显是一个元组。而我们在用正则表达式进行匹配的时候就定了元组的大小是2,如果我们定下URL的规则,还可以直接用下面的方法来指定好参数的名称

    def delete(request,table_name,delete_id):
        print("table:{},delete_id{}".format(table_name,delete_id))

    这样的效果可以直接定义到路由中。

  • 相关阅读:
    Vue学习笔记vueelementadmin 前端学习
    Vue学习笔记Vue.js2.X 学习(三)===>组件化高级
    Vue学习笔记rest_framework_jwt 学习
    Vue学习笔记Django REST framework3后端接口API学习
    Vue学习笔记Vue.js2.X 学习(一)===>基本知识学习
    Vue学习笔记Vue.js2.X 学习(二)===>组件化开发
    Vue学习笔记Windows系统Git安装(按装vueelementadmin报错)
    跑马灯
    使用信号量的线程同步实验
    按键盘数码管显示实验
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/12556026.html
Copyright © 2011-2022 走看看