zoukankan      html  css  js  c++  java
  • Django之Urls.py模块

    Django之路由层

    一 路由的作用

    ​ 路由即请求地址与视图函数的映射关系,如果把网站比喻为一本书,那路由就好比是这本书的目录,在Django中路由默认配置在urls.py中,如下图:

    urls

    二 简单的路由配置

    # urls.py 
    from django.conf.urls import url
    
    # 由一条条映射关系组成的urlpatterns这个列表称之为路由表
    urlpatterns = [
         url(regex, view, kwargs=None, name=None), # url本质就是一个函数
    ]
    #函数url关键参数介绍
    # regex:正则表达式,用来匹配url地址的路径部分,
            # 例如url地址为:http://127.0.0.1:8001/index/,正则表达式要匹配的部分是index/
    # view:通常为一个视图函数,用来处理业务逻辑
    # kwargs:略(用法详见有名分组)
    # name:略(用法详见反向解析)
    

    案例:

    urls.py文件

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views # 导入模块views.py
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        
        url(r'^index/$',views.index), # 新增一条
    ]
    

    views.py文件

    from django.shortcuts import render
    from django.shortcuts import HttpResponse # 导入HttpResponse,用来生成响应信息
    
    # 新增视图函数index
    def index(request):
        return HttpResponse('index page...')
    

    测试:

    python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/index/ 会看到 index page...
    

    注意一:

    刚刚我们在浏览器输入:http://127.0.0.1:8001/index/,Django会拿着路径部分index/去路由表中自上而下匹配正则表达式,一旦匹配成功,则立即执行其后的视图函数,不会继续往下匹配,此处匹配成功的正则表达式是 r'^index/$'。

    注意二:

    但是我们在浏览器输入:http://127.0.0.1:8001/index,Django同样会拿着路径部分index去路由表中自上而下匹配正则表达式,貌似并不会匹配成功任何正则表达式( r'^index/$'匹配的是必须以 / 结尾,所以不会匹配成功index),但实际上仍然会看到结果 index page...,原因如下:

    在配置文件settings.py中有一个参数APPEND_SLASH,该参数有两个值True或False

    当APPEND_SLASH=True(如果配置文件中没有该配置,APPEND_SLASH的默认值为True),并且用户请求的url地址的路径部分不是以 / 结尾,例如请求的url地址是 http://127.0.0.1:8001/index,Django会拿着路径部分(即index)去路由表中匹配正则表达式,发现匹配不成功,那么Django会在路径后加 / (即index/)再去路由表中匹配,如果匹配失败则会返回路径未找到,如果匹配成功,则会返回重定向信息给浏览器,要求浏览器重新向 http://127.0.0.1:8001/index/地址发送请求。

    当APPEND_SLASH=False时,则不会执行上述过程,即一旦url地址的路径部分匹配失败就立即返回路径未找到,不会做任何的附加操作

    三 分组

    什么是分组、为何要分组呢?比如我们开发了一个博客系统,当我们需要根据文章的id查看指定文章时,浏览器在发送请求时需要向后台传递参数(文章的id号),可以使用 http://127.0.0.1:8001/article/?id=3,也可以直接将参数放到路径中http://127.0.0.1:8001/article/3/

    针对后一种方式Django就需要直接从路径中取出参数,这就用到了正则表达式的分组功能了,分组分为两种:无名分组与有名分组

    3.1 无名分组

    urls.py文件

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        
        # 下述正则表达式会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以位置参数的形式传给视图函数,有几个分组就传几个位置参数
        url(r'^aritcle/(d+)/$',views.article), 
    ]
    

    views.py文件

    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    
    # 需要额外增加一个形参用于接收传递过来的分组数据
    def article(request,article_id):
        return HttpResponse('id为 %s 的文章内容...' %article_id)
    

    测试:

    python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/article/3/ 会看到: id为 3 的文章内容...
    

    3.2 有名分组

    urls.py文件

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        
        # 该正则会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以关键字参数(article_id=匹配成功的数字)的形式传给视图函数,有几个有名分组就会传几个关键字参数
        url(r'^aritcle/(?P<article_id>d+)/$',views.article), 
    ]
    

    views.py文件

    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    
    # 需要额外增加一个形参,形参名必须为article_id
    def article(request,article_id):
        return HttpResponse('id为 %s 的文章内容...' %article_id)
    

    测试:

    python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/article/3/ 会看到: id为 3 的文章内容...
    

    总结:有名分组和无名分组都是为了获取路径中的参数,并传递给视图函数,区别在于无名分组是以位置参数的形式传递,有名分组是以关键字参数的形式传递。

    强调:无名分组和有名分组不要混合使用

    四 路由分发

    随着项目功能的增加,app会越来越多,路由也越来越多,每个app都会有属于自己的路由,如果再将所有的路由都放到一张路由表中,会导致结构不清晰,不便于管理,所以我们应该将app自己的路由交由自己管理,然后在总路由表中做分发,具体做法如下:

    1 创建两个app

    # 新建项目mystie2
    E:git>django-admin startproject mysite2
    # 切换到项目目录下
    E:git>cd mysite2
    # 创建app01和app02
    E:gitmysite2>python3 manage.py startapp app01
    E:gitmysite2>python3 manage.py startapp app02
    

    2 在每个app下手动创建urls.py来存放自己的路由,如下:

    app01下的urls.py文件

    from django.conf.urls import url
    # 导入app01的views
    from app01 import views
    
    urlpatterns = [
        url(r'^index/$',views.index), 
    ]
    

    app01下的views.py

    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    
    def index(request):
        return HttpResponse('我是app01的index页面...')
    

    app02下的urls.py文件

    from django.conf.urls import url
    # 导入app02的views
    from app02 import views
    
    urlpatterns = [
        url(r'^index/$',views.index), 
    ]
    

    app02下的views.py

    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    
    def index(request):
        return HttpResponse('我是app02的index页面...')
    

    3 在总的urls.py文件中(mysite2文件夹下的urls.py)

    from django.conf.urls import url,include
    from django.contrib import admin
    
    # 总路由表
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        
        # 新增两条路由,注意不能以$结尾
        # include函数就是做分发操作的,当在浏览器输入http://127.0.0.1:8001/app01/index/时,会先进入到总路由表中进行匹配,正则表达式r'^app01/'会先匹配成功路径app01/,然后include功能会去app01下的urls.py中继续匹配剩余的路径部分
        url(r'^app01/', include('app01.urls')),
        url(r'^app02/', include('app02.urls')),
    ]
    

    测试:

    python manage.py runserver 8001  
    # 在浏览器输入:http://127.0.0.1:8001/app01/index/ 会看到:我是app01的index页面...
    # 在浏览器输入:http://127.0.0.1:8001/app02/index/ 会看到:我是app02的index页面...
    

    五 反向解析

    ​ 在软件开发初期,url地址的路径设计可能并不完美,后期需要进行调整,如果项目中很多地方使用了该路径,一旦该路径发生变化,就意味着所有使用该路径的地方都需要进行修改,这是一个非常繁琐的操作。

    解决方案就是在编写一条url(regex, view, kwargs=None, name=None)时,可以通过参数name为url地址的路径部分起一个别名,项目中就可以通过别名来获取这个路径。以后无论路径如何变化别名与路径始终保持一致。

    上述方案中通过别名获取路径的过程称为反向解析

    案例:登录成功跳转到index.html页面

    在urls.py文件中

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        
        url(r'^login/$', views.login,name='login_page'), # 路径login/的别名为login_page
        url(r'^index/$', views.index,name='index_page'), # 路径index/的别名为index_page
    ]
    

    在views.py中

    from django.shortcuts import render 
    from django.shortcuts import reverse # 用于反向解析
    from django.shortcuts import redirect #用于重定向页面
    from django.shortcuts import HttpResponse
    
    def login(request):
        if request.method == 'GET':
            # 当为get请求时,返回login.html页面,页面中的{% url 'login_page' %}会被反向解析成路径:/login/
            return render(request, 'login.html')
        
        # 当为post请求时,可以从request.POST中取出请求体的数据
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        if name == 'kevin' and pwd == '123':
            url = reverse('index_page')  # reverse会将别名'index_page'反向解析成路径:/index/       
            return redirect(url) # 重定向到/index/
        else:
            return HttpResponse('用户名或密码错误')
    
    
    def index(request):
        return render(request, 'index.html')
    

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录页面</title>
    </head>
    <body>
    <!--强调:login_page必须加引号-->
    <form action="{% url 'login_page' %}" method="post">
        {% csrf_token %} <!--强调:必须加上这一行,后续我们会详细介绍-->
        <p>用户名:<input type="text" name="name"></p>
        <p>密码:<input type="password" name="pwd"></p>
        <p><input type="submit" value="提交"></p>
    
    </form>
    </body>
    </html>
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
    <h3>我是index页面...</h3>
    </body>
    </html>
    

    测试:

    python manage.py runserver 8001  
    # 在浏览器输入:http://127.0.0.1:8001/login/ 会看到登录页面,输入正确的用户名密码会跳转到index.html
    # 当我们修改路由表中匹配路径的正则表达式时,程序其余部分均无需修改
    

    总结:

    在views.py中,反向解析的使用:
        url = reverse('index_page')
    在模版login.html文件中,反向解析的使用
        {% url 'login_page' %}
    
  • 相关阅读:
    2、容器初探
    3、二叉树:先序,中序,后序循环遍历详解
    Hebbian Learning Rule
    论文笔记 Weakly-Supervised Spatial Context Networks
    在Caffe添加Python layer详细步骤
    论文笔记 Learning to Compare Image Patches via Convolutional Neural Networks
    Deconvolution 反卷积理解
    论文笔记 Feature Pyramid Networks for Object Detection
    Caffe2 初识
    论文笔记 Densely Connected Convolutional Networks
  • 原文地址:https://www.cnblogs.com/cheng825/p/11722043.html
Copyright © 2011-2022 走看看