• Django04_路由分发


    Django04_路由分发


    4.1 路由概述

    路由, 是一种映射关系!是把客户端请求的 url 路径和用户请求的应用程序

    指django里面的视图进行绑定映射的一种关系。

    注意:请求路径和视图函数不是一对一映射关系!

    django中所有的路由最终都被保存到一个变量 urlpatterns中, urlpatterns必须声明在主应用下的urls.py总路由中。

    image-20230727233915722

    这是由配置文件settings设置的

    image-20230727233925698

    客户端发送了一个 http 请求到服务端,服务端的web服务器则会从http协议中提取url地址, 从程序内部找到项目中添加到urlpatterns里面的所有路由信息的url进行遍历匹配。如果相等或者匹配成功,则调用当前url对象的视图方法。

    在给urlpatterns路由列表添加路由的过程中,django一共提供了2个函数给开发者注册路由.

    from django.urls import path      # 字符串路由
    from django.urls import re_path   # 正则路由,会把url地址看成一个正则模式与客户端的请求url地址进行正则匹配
    
    # path和re_path 使用参数一致.仅仅在url参数和接收参数时写法不一样
    
    • 1
    • 2
    • 3
    • 4

    4.2 静态文件路由

    1. 在项目根目录下创建一个static目录

    image-20230727234553063

    1. 在settings.py中写上配置信息
    STATIC_URL = '/static/'
    # /static/代表页面去访问的地址
    STATICFILES_DIRS = [
     os.path.join(BASE_DIR, 'static')
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里的static代表它在你项目中的路径

    image-20230727234642662

    1. 去访问 static 下的文件,比如创建一个 test.txt

    url : http://127.0.0.1:8000/static/test.txt

    image-20230727234833207

    4.3 path普通路由

    在前面说到过 from django.urls import path 是用于字符串路由控制的,也就是普通的路由配置

    from django.contrib import admin
    from django.urls import path
    from ntime.views import times
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('times',times) # 当请求 /times/ 路径时,会被 times/ 所匹配,去执行 times 这个视图函数
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注意:如果我想匹配/times/下的任意数字(比如:/times/123),都想被index函数去执行,就没法办到了!

    4.5 正则匹配

    如果需要匹配/times/下的任意数字,就需要使用正则匹配

    from django.urls import re_path   # 正则路由
    
    • 1
    from django.urls import re_path
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('times',times),#当请求 /times/ 路径时,会被 times/ 所匹配,去执行 times 这个视图函数
    
        re_path(r'times/\d/',times)
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    使用正则表达式进行路径匹配

    比如:访问 times/任意数字 都会被times/\d/进行成功匹配 从而去执行times函数

    image-20230727235931754

    4.5 分组匹配—无名分组

    如果在times函数中,我想接收所匹配的内容,就需要要使用到分组匹配(就是需要接收到路由传递的数据)

     re_path(r'times/(\d\d)',times)# 将 (\d\d) 所匹配的值,传递给 times 函数
    
    • 1

    此时,需要 times 函数进行接收

    def times(request,str):
        now = datetime.datetime.now().strftime("%Y-%m-%d %X")
        print(str)
        return HttpResponse(now+"::"+str,)
        # return render(request, "timer.html", {"now": now})
    
    • 1
    • 2
    • 3
    • 4
    • 5

    image-20230728000958930

    由于是无名分组,这里times``函数的接收参数str,可以随便写

    4.6 分组匹配-有名分组

    from ntime import views
    
    urlpatterns = [
        ......
        re_path('book/(?P\w\w)/', views.book),
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    将(?P\d\d)匹配的内容以booke_name的关键字传递给book这个函数,那么book这个函数的参数必须是booke_name

    def book(request, booke_name):
        print(booke_name)
        return HttpResponse(booke_name)
    
    • 1
    • 2
    • 3

    image-20230728002129456

    4.7 多个app的路由分发

    比如我这里有两个子应用

    image-20230728002756843

    这个时候如果需要在 urls.py 进行路由跳转等,就需要使用路由分发 include

    先在子应用 app01中创建 utls.py

    image-20230728004002814

    在此 urls.pt中添加路由代码

    from django.urls import path,re_path
    from app01 import views
    
    urlpatterns = [
        re_path('book/(?P\w\w)/', views.book),
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    app01 的 views

    from django.shortcuts import render, HttpResponse
    
    # Create your views here.
    def book(request, booke_name):
        print(booke_name)
        return HttpResponse("这是app01:"+booke_name)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    同理,ntime 子应用中 也需要 创建 urls.py

    ntime 的 urls

    from django.urls import path,re_path
    from ntime import views
    
    urlpatterns = [
        re_path('book/(?P\w\w)/', views.book),
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ntime 的 views

    def book(request, booke_name):
        print(booke_name)
        return HttpResponse("这是ntime:" + booke_name)
    
    • 1
    • 2
    • 3

    主应用的 urls

    urlpatterns = [
        ......
        re_path('^app01/',include('app01.urls')),
        re_path('^ntime/',include('ntime.urls')),
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    比如:

    请求 app01/book/ss, 将会被 app01/ 所匹配,并将请求导向到 app01 的 urls.py

    image-20230728005543738

    4.8 path路径转换器

    在4.4 的re_path的时候,在里面可以写正则表达式,进行匹配路径,特别的方便

    在path路径分发的时候,也可以进行随意匹配

    写法如下:

    path('login//', views.login),
    
    • 1

    这里的就是一种通用匹配方式

    • str:匹配任何非空字符串,不包括路径分隔符’/'。如果转换器不包含在表达式中,这是默认值。
    • int:匹配零或任何正整数。返回一个int。
    • slug:匹配由ASCII字母或数字组成的字符串,以及横线和下划线字符。例如, building-your-1st-django_site可以匹配,django_@site是不可以匹配的。
    • uuid:匹配格式化的UUID。为防止多个URL映射到同一页面,必须包含破折号,并且字母必须是小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID实例。
    • path:匹配任何非空字符串,包括路径分隔符 ‘/’,可以匹配完整的URL路径,而不仅仅是URL路径的一部分str,使用时要谨慎,因为可能造成后续的所有url匹配都失效。

    使用path中的通用匹配,就好比re_path中的有名分组,将匹配的内容传递给y

    并且需要注意的是,int这个匹配规则,会将匹配上的数字,转换为int类型(这个写法为 转换器)

    4.9 自定义路径转换器

    使用django自带的path方法中的匹配规则,有点不太够用的时,就需要自定义转换器

    步骤:

    1. 新建一个 converters.py文件,里面新建一个类MonConvert

    image-20230729013531695

    1. 在类中编写代码,to_python,to_url方法必不可少
    • to_python(self, value)方法,它处理匹配的字符串转换成要传递到视图函数的类型。
    • to_url(self, value)方法,用于处理将Python类型转换为URL中使用的字符串。
    from django.urls import path, register_converter
    from app01 import views
    
    
    # 自定义转换器
    class MonConvert:
        # 自定义规则(正则表达式)
        regex = '\d\d'
    
        def to_python(self, value):
            # 这里的value就是匹配的值
            # 可以在这里对匹配的值进行一个操作
            return int(value)
    
        # 反向解析
        def to_url(self, value):
            return value
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1. 将这个类注册在转换器中

    编写好之后,最好是将这个类放入到一个公共的地方

    例如我放在app01下的converter.py

    我需要在app01下的__init__.py中注册这个模块

    # init.py
    from app01 import converter
    
    • 1
    • 2

    如果需要编写多个自定义转换器,只需要写多个类即可

    1. 在路由中使用
    # 注册转换器   类,转换器名称
    register_converter(MonConvert, 'yyy')
    
    urlpatterns = [
        # <转换器名称:关键字参数名称>
        path('login//', views.login, name='login'),
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.10 案例-登陆验证

    1. app01 的 urls中配置路由 login/
    from django.urls import path,re_path
    from app01 import views
    
    urlpatterns = [
        re_path('book/(?P\w\w)/', views.book),
        re_path('login/',views.login),
        re_path('index/',views.index)
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. app01 的 views中编写登陆函数:
    import datetime
    
    from django.shortcuts import render, HttpResponse, redirect
    
    
    # Create your views here.
    def book(request, booke_name):
        print(booke_name)
        return HttpResponse("这是app01:" + booke_name)
    
    
    def index(request):
        now = datetime.datetime.now().strftime("%Y-%m-%d %X")
        return render(request, "timer.html", {"now": now})
    
    
    def login(request):
        # 获取get请求参数用这个
        # name = request.GET.get('name')
        # pwd = request.GET.get('pwd')
        # print(name, pwd)
    
        # 获取post请求参数用这个
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        print(name, pwd)
        if name == '张三' and pwd == '1234':
            return redirect('/app01/index/')  # 重定向
        return render(request, 'login.html')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    1. templates模板中创建 登陆页面 login.html:
    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登陆title>
    head>
    <body>
    <form action="" method="post">
        <label for="name">用户名:label>
        <input type="text" value="请输入用户名" name="name" id="name">
        <br>
        <label for="pwd">密码:label>
        <input type="text" value="请输入密码" name="pwd" id="pwd">
        <br>
        <input type="submit" value="登陆">
    form>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    1. 运行,输入url地址:http://127.0.0.1:8000/app01/login

    image-20230728021708005

    当点击登陆时会报错:

    image-20230728021748305

    这是由于Django的CSRF安全机制,跨域POST请求时不允许直接使用

    settings.py中的 MIDDLEWARECsrfViewMiddleware注释掉

    image-20230728022210766

    重新输入

    image-20230728022822116

    image-20230728023837089

    4.11 拓展——请对与响应对象

    请求对象:

    1. 获取请求路径 request.path
    2. 请求方式 request.method
    3. 请求的参数 request.GET get请求参数
    4. 请求的主机 request.get_host()

    响应对象:

    1. render 返回一个页面
    return render(request, 'index.html')  # index.html是在templates中的路径
    
    • 1
    1. HttpResponse 返回字符串
    return HttpResponse("hello world")  # 直接写要返回的字符串
    
    • 1
    1. redirect 重定向到一个地址
    return rediect('/login/')   # 直接写跳转的路径, 如果使用了include,也要补全app的路径
    
    • 1
  • 相关阅读:
    .Net项目混淆/加密工具
    Java测试(11) --- selenium
    RT-Thread Studio学习(十二)W25Q128(SPI)的读写
    2D 直方图
    mvn deploy tongweb-embed-7.0.E.5_P3 依赖上传
    Air72XUX平台secure boot使用说明
    Transformers基本组件(二)快速入门Datasets、Evaluate、Trainer
    js---构造函数
    SQL注入漏洞代码分析
    java学习--day22(进程&线程)
  • 原文地址:https://blog.csdn.net/qq_40663855/article/details/132799477