首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >04路由层反向解析-名称空间-路径转换器

04路由层反向解析-名称空间-路径转换器

原创
作者头像
用户11819458
发布2025-09-02 23:58:19
发布2025-09-02 23:58:19
3500
代码可运行
举报
运行总次数:0
代码可运行

今日习题

代码语言:javascript
代码运行次数:0
运行
复制
# 1.Django的生命周期流程
# 2.Django的数据库orm操作
# 3.Django的数据库和MySQL对应关系,如何将Django中定义的模型表变成数据库中的
# 4.写出你知道的request对象的方法有哪些

上周内容回顾

代码语言:javascript
代码运行次数:0
运行
复制
# 【一】纯手撸web框架
# 【1】TCP的客户端和服务端
# 用浏览器充当客户端 ---> 访问 TCP 服务端
# 正常可以请求进去 请求无法在浏览器中响应
# TCP服务段没有遵循HTTP协议的响应模型

# 【2】改善了TCP服务端
# 遵循 HTTP 协议的响应模型
'''
请求首行 请求方式 请求路径(请求参数) HTTP协议版本
请求头   一堆 K:v键值对
换行     \r\n
请求体数据

# 如果是 GET 请求 ---> 携带的请求参数 在 请求首行 中 http:127.0.0.1:8000/?username=dream
# 如果是 POST 请求 ---> 请求地址不会携带参数 http:127.0.0.1:8000 携带的数据变成二进制数据 放在了请求其体中
'''

'''
响应首行 响应状态码 HTTP协议版本
响应头   一堆 K:v键值对
换行     \r\n 
响应体数据 

# 200 OK 标识正常响应
'''

# 【3】进行了路由分发
# 自己创建 url 和 view 的视图映射关系
# 进行分层

# 【4】借助了 wsgiref 模块 ---> 帮助我们启动和相应数据
'''
from wsgiref import simple_server
def run(request,response):
    #= 在 request 对象中有一个PATH_INFO
    # 首先要响应状态码
    response("200  OK",[])
    return [b"666"]
server = simple_server.make_server(
    host="127.0.0.1",port=9696,app=run
)
server.serve_forever()
'''

# 【5】借助 jinja2 渲染前端的页面文件
'''
from jinja2 import Template

data = "HTML源码"

# 根据页面源码创建前端对象
temp_obj = Template(data)

# 将后端的数据传递给前端进行渲染 (这步可以省略)
obj = temp_obj.render({})
'''

# 【二】Django框架安装
# 【1】注意事项
# 1. Django的项目路径不不要带中文 以及特殊字符
# 2. 打开Django项目的时候是两层 ****

# 【2】安装
# pip install django  # 默认安装最新版本 5.x 不用
# pip install django==3.2.12 # 安装我们需要的版本

# 【3】如何检验当前安装成功
# 1. 在安装的时候的控制台输出 如果已经安装过会提示已经安装在那个解释器上面了
# 2. 在你的当前的解释器的 scripts 文件夹下 多了一 django-admin.exe

# 【4】django的基本使用 --- 命令行使用
# (1)创建项目
# django-admin startproject 项目名
# (2)创建app
# 创建项目完成后会提示你 cd 项目名
# python manage.py startapp app名字
# (3)启动Django项目
# python manage.py runserver [ip:port]
# 默认不写的情况下使用的是 本地的 IP 和 PORT 127.0.0.1:8000
# 【5】django的基本使用 --- PyCharm使用
# (1)创建项目
# file -- new project -- Django  -- 配置项目参数 -- create -- 项目创建成功
# (2)创建app
# 打开 Tools -- run manage.py task -- 进入到新的终端中
# 自动创建成功 app  startapp app 名字
# 如果是使用的命令行创建的 APP 就必须自己手动注册app
# 但是 新终端 创建的 app 会自动帮助我们注册 app
# 在settings.py 中的 INSTALLED_APPS
'''
# 方式一 写全路径
"user.apps.UserConfig"
# 方式二 简写 app 名字
"user"
'''
# (3)启动项目
# 点击右上角的启动按钮
# 点击项目名修改项目配置
# 会报错 提示你启动Django支持 --- fix ---> settings --- django support -- 选择项目的根路径和配置文件路径即可

# 【三】小白必会三板斧
# 【1】HttpResponse
# 渲染纯文本内容
# 【2】render
# render(request,"前端文件名",{一些键值对})
# 渲染前端模版文件
# 【3】redirect
# 重定向路由
# redirect("写完整路径 127.0.0.1:8000/login/")
# redirect("写半完整路径 /login/")
# redirect("借助路由解析 reverse("当前路由的别名")")

# 【四】静态模版语法 -- static 语法
# 【1】在settings.py 文件中进行配置
# 【2】添加配置
'''
# 这个不用改
STATIC_URL = '/static/'
# 加一个参数 静态资源路径
STATICFILES_DIRS = [
    "static" # 自己创建
]
'''
# 【3】使用静态文件语法
# 主要用于前端的静态文件渲染
# 先加载静态文件系统 {% load static %}
# 使用静态文件夹 { % static '当前想要的文件在 static 文件夹下的路径' % }

# 【五】request对象方法

# request对象 请求对象 在每一个视图函数上面都必须带 request对象
# 封装了当前请求
# 借助前端的 form 表单提交请求
# <form action="" method>
'''
action 当前请求提交的地址
    不写 : 谁渲染的我,地址就是谁
    全写 : 写全路径 http://127.0.0.1:8000/login/
    半写 : 写半个路径 /login/
    借助路由系统 : {% url '路由的别名' %} 
method 当前请求方式
    不写 : 默认就是 get 请求
    写 : get / post 
'''

# 前端 form 表单提交 post 请求的时候 后端的 Django 会报错 CSRF 校验错误
# 解决办法 找到 settings.py 中的配置项 MIDDLEWARE ---> CsrfViewMiddleware 注解掉

# 【1】request.method
# 获取到当前的请求方式 get / post

# 【2】request.GET ---> 类似于字典的对象
# 获取到 get 请求携带的请求参数
# request.GET.get 获取到单一键值对数据
# request.GET.getlist 获取到 一个键对应多个值的数据

# 【3】request.POST
# 获取到 POST 请求携带的请求体数据
# request.POST.get 获取到单一键值对数据
# request.POST.getlist 获取到 一个键对应多个值的数据

# 【七】Django的ORM框架入门
# 【1】ORM框架
# 借助 其他语言 来操作我们数据库中的数据的框架
# Django的 ORM 框架 好用
# sqlarmchary

# 【2】配置数据库
# (1)Django的默认数据库
# 启动Django项目后会默认创建一个 db.sqlite3 文件 类似于 MySQL中的数据库和表
# db.sqlite3 ---> 存数据

# (2)Django连接MySQL 数据库
# 在settings.py 中配置数据库
'''
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': "django_day04",
        "HOST": "127.0.0.1",  # IP 是字符串
        "PORT": 3306,  # 端口是数字
        "USER": "root",
        "PASSWORD": "1314521",
        "CHARSET": "utf8mb4"
    }
}
'''

# (3)连接 MySQL 报错
'''
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?
'''
# 解决方式一:打猴子补丁
# pip install pymysql
'''
import pymysql
pymysql.install_as_MySQLdb()
'''
# 结局方式二:安装 mysqlclient 模块
# pip install mysqlclient
# window系统上没有问题但是MacOS装不上

# 【3】ORM框架中的数据如何映射到数据库中
# ORM框架中的 类 ---> MySQL 数据库中的 表
# ORM框架中的 类属性 ---> MySQL 数据库中的 表字段
# ORM框架中的 类实例 ---> MySQL 数据库中的 数据
'''
# 定义模型表
class User(models.Model):
    # 定义模型表字段 ---> 数据库中的一些参数相关联
    # username varchar(32) null 
    username = models.CharField(max_length=32, null=True)

    # password varchar(32) not null 
    password = models.CharField(max_length=32, null=False)

    # age int()
    age = models.IntegerField()

    # gender varchar(32) default "male"
    gender = models.CharField(max_length=32, default="male")
'''
# Django中定义的模型表迁移到数据库中
'''
python manage.py makemigrations 
python manage.py migrate

# 借助 新终端 
'''

# 【4】ORM操作
# (1)查看数据
# model.objects.filter() ---> 列表
# model.objects.get() ---> 具体的对象 获取不到就报错 只能获取一个

# (2)新增数据
# model.objects.create()
# model().save()

# (3)删除数据
# model.objects.filter().delete()
# model.objects.get().delete()

# (4)更新数据
# model.objects.filter().update()
# model.objects.get().字段名 = 字段值 ---> save

# 【八】Django的生命周期流程图
# 浏览器发起请求 ---> 地址栏输入的=是一串地址 ---> DNS 解析 解析成 ip和端口
# Django的框架前面 wsgiref 模块中 ---> 将浏览器的请求打包成 符合 HTTP协议的请求和 符合Django的请求
# Django的中间件 类似于保安 , 对请求进行拦截和校验
# Django的 urls 做路由分发
# Django的 view 做视图处理
# 渲染前端文件 / 连接数据库处理数据 .... 日志记录 ...
# Django的 view 要返回响应数据
# 经过 Django的 urls
# Django框架前面的 wsgiref 模块 将Django的请求独享转换为 符合HTTP协议的响应独享
# 浏览器进行渲染

# 【九】Django的路由层
# 【1】语法更新
# Django1.x : url(r"^正则表达式",视图函数地址)
# Django2.x : path("路径",视图函数地址)  /  re_path(r"^正则表达式",视图函数地址)

# 【2】路由相似的问题
# test / testadd ---> 用正则写的时候会被拦截到
# 解决办法就是 在路径后面加 / 作为分隔符

# 【3】有名分组和无名分组 ---> 相较于正则表达式来说
# (1)无名分组
# 在路由中定义 re_path("^page/(\d+)/",page)
# http://127.0.0.1:8000/page/1/
# 在视图函数中,接收到路由中传入的任意数字是 用 可变长位置参数接受的 可以在视图函数上面有一个任意名字的位置参数接收到
'''
def page(request,id): # id 是可以改成任意的参数名的
    return ...
'''
# (2)有名分组
# 在路由中定义 re_path("^page/(?P<id>\d+)/",is_page)
# # http://127.0.0.1:8000/page/1/
# 在视图函数中,接收到路由中传入的任意数字是 用 可变长关键字参数接受的 在视图函数中必须用指定的关键字接收到参数
'''
def is_page(request,id): # id 必须叫id 否则会报错
    return ...
'''

# 【4】反向解析
# 在某些路由中可能会非常复杂 ---> 不好记 并且定义的时候出现问题
# Django同给我们一个语法 路由解析语法
# (1)在路由中定义当前路由映射的名字
# path("login/",login,name="login")
# (2)使用
# 前段
# 借助路由语法 {% url "login" %}
# 后端
# 借助 解析语法 reverse("login")

今日内容详细

【一】有名分组和无名分组的反向解析

【1】前端

  • 有名分组和无名分组 直接在解析语法的后面仿参数即可
代码语言:javascript
代码运行次数:0
运行
复制
<p>
    http://127.0.0.1:8000/parse_name/1/
</p>
<p>
    <a href="/parse_name/1/">有名分组</a>
</p>
<p>
    // Reverse for 'parse_name' with no arguments not found. 1 pattern(s) tried: ['parse_name/(?P<id>\\d+)']
    <a href="{% url 'parse_name' 5 %}">有名分组</a>
</p>
<p>
    http://127.0.0.1:8000/parse_no_name/1/

</p>
<p>
    <a href="/parse_no_name/1/">无名分组</a>
</p>
<p>
    <a href="{% url 'parse_no_name' "4" %}">无名分组</a>
</p>

【2】后端

  • 有名分组
代码语言:javascript
代码运行次数:0
运行
复制
def parse_name(request, *args, **kwargs):
    print(args)  # ()
    print(kwargs)  # {'id': '1'}
    # args : 按照位置传递参数
    # kwargs :按照关键字传递参数
    id = kwargs.get("id")
    # http://127.0.0.1:8000/parse_name_redirect/(?P<id>\d+)/
    # return redirect(reverse("parse_name_redirect", args=(id,)))
    # 如果是按照关键字传递参数建议 同名传
    # return redirect(reverse("parse_name_redirect", kwargs={"name": id}))
    # Reverse for 'parse_name_redirect' with keyword arguments '{'name': '1'}' not found. 1 pattern(s) tried: ['parse_name_redirect/(?P<id>\\d+)/']
    return redirect(reverse("parse_name_redirect", kwargs={"id": id}))
  
# http://127.0.0.1:8000/parse_name_redirect/
# reverse("parse_name_redirect") # 没有参数的时候
# 有名分组
# http://127.0.0.1:8000/parse_name_redirect/(?P<id>\d+)/
# http://127.0.0.1:8000/parse_name_redirect/1/
# 进入到视图函数中 kwargs {"id":"1"}
# 从一个视图函数中解析定向到 另一个 有名分组的视图函数的时候
# reverse("parse_name_redirect",args=(1,)) # 有几个参数传入几个参数
# reverse("parse_name_redirect",kwargs={"id":"1"}) # 有几个参数传入几个参数
# reverse("parse_name_redirect",kwargs={"name":"1"}) # 报错 找不到 name 关键字 定义的路由上的关键字叫 id
  • 无名分组
代码语言:javascript
代码运行次数:0
运行
复制
def parse_no_name(request, *args, **kwargs):
    print(args)  # ('1',)
    print(kwargs)  # {}
    id = args[0]
    return redirect(reverse("parse_no_name_redirect", args=(id,)))
    # Reverse for 'parse_no_name_redirect' with keyword arguments '{'name': '1'}' not found. 1 pattern(s) tried: ['parse_no_name_redirect/(\\d+)/']
    # return redirect(reverse("parse_no_name_redirect", kwargs={"name":id}))
    
# http://127.0.0.1:8000/parse_no_name_redirect/
# reverse("parse_no_name_redirect") # 没有参数的时候
# 无名分组 --- 对参数名字没有要求
# http://127.0.0.1:8000/parse_no_name_redirect/(\d+)/
# http://127.0.0.1:8000/parse_no_name_redirect/1/
# reverse("parse_no_name_redirect",args=(id,))
# reverse("parse_no_name_redirect",kwargs={"id":"1"}) # 报错 在路由定义的时候缺少关键字
  • 总结
代码语言:javascript
代码运行次数:0
运行
复制
# 【总结】
# 后端 无名分组 直接用 args 传参数
# 后端 有名分组 直接用 args 传参数 / 用 kwargs 传参数但是 键 必须和路由重定义的关键字是一样的

【二】路由分发

代码语言:javascript
代码运行次数:0
运行
复制
# 方案一:在每一个 app 的路由上增加标识 --- > 杂乱无章
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', index, name="index"),
    # SHOP app 下面的路由映射
    path("shop/order/", order, name="order"),
    path("shop/buy/", buy, name="buy"),

    # USER app 下面的路由映射
    # 有名分组 http://127.0.0.1:8000/parse_name/1/
    re_path("^user/parse_name/(?P<id>\d+)/", parse_name, name="parse_name"),
    # 无名分组
    re_path("^user/parse_no_name/(\d+)/", parse_no_name, name="parse_no_name"),
    re_path("^user/parse_name_redirect/(?P<id>\d+)/", parse_name_redirect, name="parse_name_redirect"),
    re_path("^user/parse_no_name_redirect/(\d+)/", parse_no_name_redirect, name="parse_no_name_redirect"),
]
代码语言:javascript
代码运行次数:0
运行
复制
# 方案二:方案一如果路由太多 就会导致杂乱无章,于是进行拆解
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', index, name="index"),
]
# 当前路由列表中只放自己app下的路由关系
shop_urlpatterns = [
    # SHOP app 下面的路由映射
    path("shop/order/", order, name="order"),
    path("shop/buy/", buy, name="buy"),
]
# 当前路由列表中只放自己app下的路由关系
user_urlpatterns = [
    # USER app 下面的路由映射
    # 有名分组 http://127.0.0.1:8000/parse_name/1/
    re_path("^user/parse_name/(?P<id>\d+)/", parse_name, name="parse_name"),
    # 无名分组
    re_path("^user/parse_no_name/(\d+)/", parse_no_name, name="parse_no_name"),
    re_path("^user/parse_name_redirect/(?P<id>\d+)/", parse_name_redirect, name="parse_name_redirect"),
    re_path("^user/parse_no_name_redirect/(\d+)/", parse_no_name_redirect, name="parse_no_name_redirect"),
]
urlpatterns += shop_urlpatterns
urlpatterns += user_urlpatterns
代码语言:javascript
代码运行次数:0
运行
复制
# 方案三:将每一个app下面的 路由拆解到自己的app下面
from user.urls import user_urlpatterns
from shop.urls import shop_urlpatterns
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', index, name="index"),
]

urlpatterns += shop_urlpatterns
urlpatterns += user_urlpatterns
代码语言:javascript
代码运行次数:0
运行
复制
# 方案四:Django提供给我们分发语法
from shop.views import order, buy
from user.views import parse_name, parse_no_name, parse_name_redirect, parse_no_name_redirect
# 当前路由列表中只放自己app下的路由关系
shop_urlpatterns = [
    # SHOP app 下面的路由映射
    path("order/", order, name="order"),
    path("buy/", buy, name="buy"),
]
# 当前路由列表中只放自己app下的路由关系
user_urlpatterns = [
    # USER app 下面的路由映射
    # 有名分组 http://127.0.0.1:8000/parse_name/1/
    re_path("^parse_name/(?P<id>\d+)/", parse_name, name="parse_name"),
    # 无名分组
    re_path("^parse_no_name/(\d+)/", parse_no_name, name="parse_no_name"),
    re_path("^parse_name_redirect/(?P<id>\d+)/", parse_name_redirect, name="parse_name_redirect"),
    re_path("^parse_no_name_redirect/(\d+)/", parse_no_name_redirect, name="parse_no_name_redirect"),
]

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', index, name="index"),
    # shop app
    path("shop/", include(shop_urlpatterns)),
    # http://localhost:8000/user/parse_name_redirect/5/
    path("user/", include(user_urlpatterns))

]
代码语言:javascript
代码运行次数:0
运行
复制
# 方案五:在每一个app下面都有一个 urls.py ---> 每一个人都有 一个 urlpatterns
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', index, name="index"),
    # shop app
    path("shop/", include("shop.urls")),
    # http://localhost:8000/user/parse_name_redirect/5/
    path("user/", include("user.urls"))
]
# 前提是 每一个app 下面都有一个 urls.py 文件 并且 其中的列表名字必须叫 urlpatterns 并且必须有 空列表

【三】应用名称空间

【1】引入

代码语言:javascript
代码运行次数:0
运行
复制
# 【一】创建两个app
# app01 和 app02
# 【二】在两个 app下都有 index 函数
# 【0】路由分发
'''
path("app01/", include("app01.urls")),
path("app02/", include("app02.urls")),
'''
# 【1】app01
# (1)urls.py
'''
from app01.views import index

urlpatterns = [
    path("index/", index, name="index_view")
]
'''
# (2)view.py
'''
from django.shortcuts import render, reverse, HttpResponse
# Create your views here.
def index(request):
    print(f"from app01 view :>>>> {reverse('index_view')}")
    return HttpResponse("app01 index")
'''
# 【2】app02
# (1)urls.py
'''
from django.urls import path

from app02.views import index

urlpatterns = [
    path("index/", index, name="index_view")
]
'''
# (2)view.py
'''
from django.shortcuts import render, reverse, HttpResponse
# Create your views here.
def index(request):
    print(f"from app02 view :>>>> {reverse('index_view')}")
    return HttpResponse("app02 index")
'''

# 【3】区别和相同
# 区别 每一个视图函数都是自己的视图函数不是共用的
# 相同 每一个视图的别名都是一样的

# user ---> login / register
# admin ---> login / register
'''
    <p>
        <a href="/app01/index/">app01 的 index </a>
        <br>
        <a href="{% url 'index_view' %}">app01 的 index (路由解析)</a>
    </p>

    <p>
        <a href="/app02/index/">app02 的 index </a>
        <br>
        <a href="{% url 'index_view' %}">app02 的 index  (路由解析)</a>
    </p>
'''

# 访问 http://127.0.0.1:8000/app01/index/ 按照指定路径访问
# 访问 http://127.0.0.1:8000/app02/index/ 按照指定路径访问

# 访问路由解析 {% url 'index_view' %} 和 视图函数中的 reverse("index_view ")
# 都解析到了 /app02/index/

# 为什么到了 app02 而不是 app01 ?
# app02 比 app01 后分发 ---> 覆盖掉了前面的分发

# 你想访问 user 下的登录页面 结果给你定向到了 admin 下面的登陆页面 ---> 出现异常了

【2】解决方案一

代码语言:javascript
代码运行次数:0
运行
复制
# 【二】解决方案一:在每一个app下面的 urls 里面做名称空间的声明
# 【0】路由分发
'''
path("app01/", include("app01.urls")),
path("app02/", include("app02.urls")),
'''
# 【1】app01
# (1)urls.py
'''
from app01.views import index
# 加一个参数 叫 app_name 名字就和自己的app名字一样
app_name = "app01"
urlpatterns = [
    path("index/", index, name="index_view")
]
'''
# (2)view.py
'''
from django.shortcuts import render, reverse, HttpResponse
# Create your views here.
def index(request):
    print(f"from app01 view :>>>> {reverse('app01:index_view')}")
    return HttpResponse("app01 index")
'''
# 【2】app02
# (1)urls.py
'''
from django.urls import path

from app02.views import index
# 加一个参数 叫 app_name 名字就和自己的app名字一样
app_name = "app02"
urlpatterns = [
    path("index/", index, name="index_view")
]
'''
# (2)view.py
'''
from django.shortcuts import render, reverse, HttpResponse
# Create your views here.
def index(request):
    print(f"from app02 view :>>>> {reverse('app02:index_view')}")
    return HttpResponse("app02 index")
'''

【3】解决方案二

代码语言:javascript
代码运行次数:0
运行
复制
# 【三】解决方案二: 在路由分发的时候就制定好各自的名称空间
# 【0】路由分发
'''
# 对每一个 app 的名称空间进行约束
# arg 是 元组 urlconf_module, app_name = arg
# urlconf_module : 你的 app 的 urls 的路径
# app_name : 以当前app名字命名即可
# namespace 声明当前的名称空间名称 和 你的app名字同名即可
path("app02/", include(arg=("app02.urls", "app02"), namespace="app02")),
path("app01/", include(arg=("app01.urls", "app01"), namespace="app01")),
'''
# 【1】app01
# (1)urls.py
'''
from app01.views import index

urlpatterns = [
    path("index/", index, name="index_view")
]
'''
# (2)view.py
'''
from django.shortcuts import render, reverse, HttpResponse
# Create your views here.
def index(request):
    print(f"from app01 view :>>>> {reverse('app01:index_view')}")
    return HttpResponse("app01 index")
'''
# 【2】app02
# (1)urls.py
'''
from django.urls import path

from app02.views import index

urlpatterns = [
    path("index/", index, name="index_view")
]
'''
# (2)view.py
'''
from django.shortcuts import render, reverse, HttpResponse
# Create your views here.
def index(request):
    print(f"from app02 view :>>>> {reverse('app02:index_view')}")
    return HttpResponse("app02 index")
'''
代码语言:javascript
代码运行次数:0
运行
复制
# 【四】应用场景
# user 用户
# login 用户登陆
# register 用户注册

# admin 管理员
# login 管理员登陆
# register 管理员注册

【四】路径转换器

代码语言:javascript
代码运行次数:0
运行
复制
# Django 2.x 之后才出现的语法
# 和你的 path 语法一起用的

# 【一】有名分组和无名分组
# 写正则表达式区分参数

# 【二】转换器
# 对上面的 正则匹配的参数进行重新约束和规范

# 【三】转换器介绍
# Django提供给我们的转换器有五种
# 但是除了这五种我们也可以自定义
# 【1】● str
#   ○ 匹配除了 '/' 之外的非空字符串。
#   ○ 如果表达式内不包含转换器,则会默认匹配字符串。
# 【2】● int **
#   ○ 匹配 0 或任何正整数。返回一个 int 。
# 【3】● slug
#   ○ 匹配任意由 ASCII 字母或数字以及连字符和下划线组成的短标签。
#   ○ 比如,building-your-1st-django-site 。
# 【4】● uuid
#   ○ 匹配一个格式化的 UUID 。为了防止多个 URL 映射到同一个页面,必须包含破折号并且字符都为小写。
#   ○ 比如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID 实例。
# 【5】● path
#   ○ 匹配非空字段,包括路径分隔符 '/' 。
#   ○ 它允许你匹配完整的 URL 路径而不是像 str 那样匹配 URL 的一部分。

# 【四】案例
# 【1】路由定义
'''
    # 【1】 ● str
    #   ○ 匹配除了 '/' 之外的非空字符串。
    #   ○ 如果表达式内不包含转换器,则会默认匹配字符串。
    # http://127.0.0.1:8000/order/str_pattern/dream/
    path("str_pattern/<str:name>/", str_pattern, name="str_pattern"),
    # 必须按照关键字接受参数 并且参数类型是字符串
    # 匹配除了 '/' 之外的非空字符串 遇到 / 就会变成指定的路由去解析
    # http://127.0.0.1:8000/order/str_pattern/dre/am/
    # 先去这里找 : http://127.0.0.1:8000/order/str_pattern/dre/ 参数是 am

    # 【2】● int
    #   ○ 匹配 0 或任何正整数。返回一个 int 。
    path("int_pattern/<int:name>/", int_pattern, name="int_pattern"),
    # 接受到的参数会被自动转换成 int 类型

    # 【3】● slug
    #   ○ 匹配任意由 ASCII 字母或数字以及连字符和下划线组成的短标签。
    #   ○ 比如,building-your-1st-django-site 。
    path("slug_pattern/<slug:name>/", slug_pattern, name="slug_pattern"),

    # 【4】● uuid
    #   ○ 匹配一个格式化的 UUID 。为了防止多个 URL 映射到同一个页面,必须包含破折号并且字符都为小写。
    #   ○ 比如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID 实例。
    path("uuid_pattern/<uuid:name>/", uuid_pattern, name="uuid_pattern"),

    # 【5】● path
    #   ○ 匹配非空字段,包括路径分隔符 '/' 。
    #   ○ 它允许你匹配完整的 URL 路径而不是像 str 那样匹配 URL 的一部分。
    path("path_pattern/<path:name>/", path_pattern, name="path_pattern"),
'''
# 【2】视图函数
'''
from django.shortcuts import render, HttpResponse


# Create your views here.
def str_pattern(request, name, *args, **kwargs):
    print(args)  # ()
    print(kwargs)  # {'name': 'dream'}
    print(name, type(name))
    return HttpResponse("str_pattern")


def int_pattern(request, name, *args, **kwargs):
    print(args)  # ()
    print(kwargs)  # {'name': 'dream'}
    print(name, type(name))
    return HttpResponse("int_pattern")


def slug_pattern(request, name, *args, **kwargs):
    print(args)  # ()
    print(kwargs)  # {'name': 'dream'}
    print(name, type(name))
    return HttpResponse("slug_pattern")


def uuid_pattern(request, name, *args, **kwargs):
    print(args)  # ()
    print(kwargs)  # {'name': 'dream'}
    print(name, type(name))
    return HttpResponse("uuid_pattern")


def path_pattern(request, name, *args, **kwargs):
    print(args)  # ()
    print(kwargs)  # {'name': 'dream'}
    print(name, type(name))
    return HttpResponse("path_pattern")
'''
# 【3】自定义路径转换器
# (1)先创建一个文件 任意命名 比如 path_converters.py
# (2)在当前文件中定义自定义转换器的逻辑
"""
# 【1】创建一个类 --->必须按照年份传入数据 2020 ---> 转成数字类型
class FourDigitYearConverter:
    # 【2】定义正则匹配规则
    # [0-9] ---> 字符组
    # {4} {n,m} --> 贪婪匹配 最少是n 最多是 m 默认按最多取
    reg = r"[0-9]{4}"

    # 【3】定义一个函数
    def to_python(self, value):
        '''
        接收到当前路径中的参数并对参数进行转换转换成Python中的数据类型
        :return: 
        '''
        return int(value)

    # 【4】定义一个函数
    def to_url(self, value):
        '''
        根据上面定义的正则匹配表达式将 url 中的参数提取出来
        # 2024 ---> 2024
        :return: 
        '''
        return "%0d4" % value
"""
# (3)使用自定义转换器
'''
# 【一】导入自定义的路径转换器类
from order.path_converters import FourDigitYearConverter
# 【二】借助Django的转换器语法转换成 Django的转换器
from django.urls import register_converter

# 【三】注册你的转换器
register_converter(FourDigitYearConverter, "aaa")

urlpatterns = [
    # 【0】自定义路径转换器
    path("self_pattern/<aaa:name>/", self_pattern, name="self_pattern"),
]
'''

【五】虚拟环境

代码语言:javascript
代码运行次数:0
运行
复制
# 【一】虚拟环境介绍
# 根据现有的环境复制出来的环境的备份

# 【二】虚拟环境的应用场景
# 项目一: Django 3.x 版本开发
# 项目二: Django 5.x 版本开发

# 如果是同一个解释器 导致的问题就是必须将另一个版本卸载然后安装指定版本才行
# 于是就出现了虚拟环境
# 为了不同项目之间的环境隔离

# 【三】创建虚拟环境的方式
# 【1】自带的 venv
# 【2】第三方模块
# 【3】Pycharm

# 【四】将项目发给别人让别人跑
# 对方不知道你安装了哪些模块
# 让对象知道有哪些模块
'''
Package           Version
----------------- -------
asgiref           3.8.1
Django            3.2.12
pip               24.2
PyMySQL           1.1.1
pytz              2024.2
setuptools        74.1.3
sqlparse          0.5.1
typing_extensions 4.12.2
wheel             0.44.0
'''
# 发给对象 让对方一个个的敲 模块名和版本号


# 【五】导出当前项目的所有模块名及版本
# 【1】导出
'''
pip freeze > requirements.txt
'''

# 会自动创建一个 文件 requirements.txt
# 并且将所有的模块名和版本号存进去
'''
asgiref==3.8.1
Django==3.2.12
PyMySQL==1.1.1
pytz==2024.2
sqlparse==0.5.1
typing_extensions==4.12.2
'''

# 【2】安装
'''
pip install -r requirements.txt
'''
# 会按照 requirements.txt 文件中的模块名和版本号自动安装模块

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 今日习题
  • 上周内容回顾
  • 今日内容详细
    • 【一】有名分组和无名分组的反向解析
      • 【1】前端
      • 【2】后端
    • 【二】路由分发
    • 【三】应用名称空间
      • 【1】引入
      • 【2】解决方案一
      • 【3】解决方案二
    • 【四】路径转换器
    • 【五】虚拟环境
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档