Django04_路由分发

Django04_路由分发


4.1 路由概述

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

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

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

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

这是由配置文件settings设置的

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

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

python 复制代码
from django.urls import path      # 字符串路由
from django.urls import re_path   # 正则路由,会把url地址看成一个正则模式与客户端的请求url地址进行正则匹配

# path和re_path 使用参数一致.仅仅在url参数和接收参数时写法不一样

4.2 静态文件路由

  1. 在项目根目录下创建一个static目录
  1. 在settings.py中写上配置信息
python 复制代码
STATIC_URL = '/static/'
# /static/代表页面去访问的地址
STATICFILES_DIRS = [
 os.path.join(BASE_DIR, 'static')
]

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

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

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

4.3 path普通路由

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

python 复制代码
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 这个视图函数
]

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

4.5 正则匹配

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

python 复制代码
from django.urls import re_path   # 正则路由
python 复制代码
from django.urls import re_path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('times',times),#当请求 /times/ 路径时,会被 times/ 所匹配,去执行 times 这个视图函数

    re_path(r'times/\d/',times)
]

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

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

4.5 分组匹配---无名分组

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

python 复制代码
 re_path(r'times/(\d\d)',times)# 将 (\d\d) 所匹配的值,传递给 times 函数

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

python 复制代码
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})

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

4.6 分组匹配-有名分组

python 复制代码
from ntime import views

urlpatterns = [
    ......
    re_path('book/(?P<booke_name>\w\w)/', views.book),
]

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

python 复制代码
def book(request, booke_name):
    print(booke_name)
    return HttpResponse(booke_name)

4.7 多个app的路由分发

比如我这里有两个子应用

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

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

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

python 复制代码
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    re_path('book/(?P<booke_name>\w\w)/', views.book),
]

app01 的 views

python 复制代码
from django.shortcuts import render, HttpResponse

# Create your views here.
def book(request, booke_name):
    print(booke_name)
    return HttpResponse("这是app01:"+booke_name)

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

ntime 的 urls

python 复制代码
from django.urls import path,re_path
from ntime import views

urlpatterns = [
    re_path('book/(?P<booke_name>\w\w)/', views.book),
]

ntime 的 views

python 复制代码
def book(request, booke_name):
    print(booke_name)
    return HttpResponse("这是ntime:" + booke_name)

主应用的 urls

python 复制代码
urlpatterns = [
    ......
    re_path('^app01/',include('app01.urls')),
    re_path('^ntime/',include('ntime.urls')),
]

比如:

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

4.8 path路径转换器

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

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

写法如下:

python 复制代码
path('login/<int:y>/', views.login),

这里的<int:y>就是一种通用匹配方式

  • 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
  1. 在类中编写代码,to_python,to_url方法必不可少
  • to_python(self, value)方法,它处理匹配的字符串转换成要传递到视图函数的类型。
  • to_url(self, value)方法,用于处理将Python类型转换为URL中使用的字符串。
python 复制代码
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. 将这个类注册在转换器中

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

例如我放在app01下的converter.py

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

python 复制代码
# init.py
from app01 import converter

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

  1. 在路由中使用
python 复制代码
# 注册转换器   类,转换器名称
register_converter(MonConvert, 'yyy')

urlpatterns = [
    # <转换器名称:关键字参数名称>
    path('login/<yyy:y>/', views.login, name='login'),
]

4.10 案例-登陆验证

  1. app01 的 urls中配置路由 login/
python 复制代码
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    re_path('book/(?P<booke_name>\w\w)/', views.book),
    re_path('login/',views.login),
    re_path('index/',views.index)
]
  1. app01 的 views中编写登陆函数:
python 复制代码
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. templates模板中创建 登陆页面 login.html:
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. 运行,输入url地址:http://127.0.0.1:8000/app01/login

当点击登陆时会报错:

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

settings.py中的 MIDDLEWARECsrfViewMiddleware注释掉

重新输入

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

请求对象:

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

响应对象:

  1. render 返回一个页面
python 复制代码
return render(request, 'index.html')  # index.html是在templates中的路径
  1. HttpResponse 返回字符串
python 复制代码
return HttpResponse("hello world")  # 直接写要返回的字符串
  1. redirect 重定向到一个地址
python 复制代码
return rediect('/login/')   # 直接写跳转的路径, 如果使用了include,也要补全app的路径
相关推荐
喝醉酒的小白10 分钟前
数据库参数备份
数据库
小徍13 分钟前
MySQL 8.0特性-自增变量的持久化
数据库·mysql
糖豆大将军14 分钟前
Mysql个人八股总结
数据库·oracle
YRr YRr23 分钟前
Ubuntu20.04 解决一段时间后键盘卡死的问题 ubuntu
linux·数据库·ubuntu
2401_8576363932 分钟前
实时数据流的革命:分布式数据库的挑战与实践
数据库·分布式
冰红茶兑滴水1 小时前
MySQL 表的约束
数据库·mysql
cui_win1 小时前
Redis高可用-Cluster(集群)
数据库·redis·bootstrap
小五Z1 小时前
MySql--增删改查表设计总结
数据结构·数据库·mysql
锐策2 小时前
〔 MySQL 〕数据类型
数据库·mysql
天天要nx2 小时前
D68【python 接口自动化学习】- python基础之数据库
数据库·python