Django路由
Django的路由urls.py文件,可以让我们高度的自定义我们的路由访问,利用正则表达式,或匹配语法,快捷的对不同路由进行分类和分发。
项目结构
─App01
│ │ admin.py
│ │ apps.py
│ │ models.py
│ │ tests.py
│ │ urls.py
│ │ views.py
│ │ __init__.py
│ │
│ ├─migrations
│ │ __init__.py
│
├─Project
│ asgi.py
│ settings.py
│ urls.py
│ wsgi.py
│ __init__.py
│
│
└─templates
1. 普通路由
1.1 普通无名路由
直接在Project/urls.py中定义
from django.contrib import admin
from django.urls import path # 导入urls包中的path
import App01.views
urlpatterns = [
path("admin/", admin.site.urls),
path("index/", App01.views.index), # 对应App01中的views.py index函数
]
# 此时访问 127.0.0.1/index/即可返回App01.views.index函数对应的值
1.2 普通有名分组路由
现在的需求是:
所有访问/file/文件名,都直接返回这个文件
例如:访问/file/文件1.csv 就返回这个文件1.csv
那么就需要有名路由将获取到的文件名称传入到视图函数中。
在 Django 中,正则路径中的有名分组(named groups)是一种用于捕获 URL 中特定部分的方法。
Django 有名分组允许从 URL 中提取特定的值,并将其作为关键字参数传递给视图函数。
在 Django 的 URL 配置中,使用尖括号 "<>" 来创建有名分组
project / urls.py文件
eg:
需求:
所有访问/file/文件名的都返回对应的文件
# 使用尖括号 "<>" 来创建有名分组
from django.contrib import admin
from django.urls import path
import App01.views
urlpatterns = [
path("admin/", admin.site.urls),
path('index/<str:file>') # 这里指定index/匹配一个str类型:并命名为file
]
# Tips: 这里分组获取到的数据,将会通过关键字参数传入视图函数,与位置无关
App01 / views.py文件
from django.shortcuts import render, HttpResponse
# Tips: 这里分组获取到的数据,将会通过关键字参数传入视图函数,与位置无关
def get_file(request,file): # 函数需要添加一个参数file
return HttpResponse(f'这是:{file}文件')
结果示例:
2. 正则路由
2.1 正则无名路由
普通的路由无法解决复杂路由的需求
例如我们现在需要让所有访问 /index+数字的都返回index函数
此时我们不可能给index1,index2…都添加到路由,这是就要使用正则路由
还有一些日期匹配等多功能的都无法通过普通路由实现,而正则表达式则可以
eg:
需求:
所有访问index+数字地址的都返回App01.views.index函数
Tips:
访问index/也会返回,所以正则要用*不能用+
# 正则路由需要使用re_path函数
from django.contrib import admin
from django.urls import path,re_path # re_path
import App01.views
urlpatterns = [
path("admin/", admin.site.urls),
re_path(r"^index\d*/$", App01.views.index), # 正则匹配所有index开头,后面任意数字或者没有数字的
]
结果示例:
2.2 正则路由有名分组
对于上面1.2所示我们已经能搞直接通过路由传递参数,但是没有正则的加成,怎么能应付了复杂情况呢?
这里引出了正则路由的有名分组
语法:
(?P<组名>正则表达式)
eg:
"date/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$" # 匹配 date/年/月 并返回year,month
例如: date/2022/09 -> year = 2022;month = 09 ->传入views函数
现在又有一个需求:
当用户访问 app+数字/files/files_name的时候就去返回data文件夹下的"{数字}+filesname"文件,并且当filesname不传入的时候,返回一个文件夹。
当app没有加数字的时候,返回文本 “请求有错误哦!”(不报错)
把这个需求拆开:
- app加任何数字才会匹配,不加数字就返回 “请求有错误哦!”
- files/files_name,当files_name是空的时候就返回文件夹,否则返回这个文件 (有名路由)
eg:
访问 127.0.0.1:8000/app60/files/文件.csv -> 就返回 "60文件.csv"文件
访问 127.0.0.1:8000/app10/files/视频.mp4 -> 就返回 "10视频.mp4"文件
访问 127.0.0.1:8000/app/files/ -> 就返回文本 “请求有错误哦!”(不报错)
访问 127.0.0.1:8000/app555/files/ -> 就返回 “文件夹”.
project - urls.py文件
from django.contrib import admin
from django.urls import path,re_path
import App01.views
urlpatterns = [
path("admin/", admin.site.urls),
re_path(r"^app(?P<num>\d*)/files/(?P<filename>.*)", App01.views.get_num_file),
# 这里不要加$,因为如果文件名不存在的时候要返回文件夹,所以不要加"/$"
]
-
结果示例: 127.0.0.1:8000/app60/files/文件.csv -> 返回 "60文件.csv"文件
-
结果示例: 127.0.0.1:8000/app10/files/视频.mp4 -> 返回 "10视频.mp4"文件
-
结果示例: 127.0.0.1:8000/app/files/ 就返回文本 “请求有错误哦!”(不报错)
- 结果示例: 127.0.0.1:8000/app555/files/ -> 就返回 “文件夹”.
3. 路由分发(子路由)
对于大型项目,我们可能会创建多个Django应用。
例如一个App,它可以有 音乐播放器,可以有商城,也可以有短视频
多个应用之间,我们往往使用不用的接口,但是可能使用相同的域名。
例如:
-
/video/api 作为短视频的接口
-
/shop/api 作为商城的接口
-
/music/api 作为音乐播放器接口
对于这类情况,我们就要用到路由分发。
我们的Django项目中,项目总文件夹中,有一个urls.py是全局路由分发的配置,但是对于每个不同的应用,我们其实也可以单独创建配置文件进行定制分发。
对于不同的路由分发,我们可以调用urls包中的 include() 进行分发
from django.contrib import admin
from django.urls import path,re_path,include
# 使用格式:
re_path|path ("路由匹配",include("子路由对应的路由匹配,文件内需要有urlpatterns定义"))
# 示例:
import App01.views
urlpatterns = [
path("admin/", admin.site.urls),
path("files/<str:file>/", include('App01.urls')), # 分发到App01应用的urls文件中
# 对应的此时,我们要打App01文件夹下创建urls.py文件
# 并且分发后的路由就会去除第一次匹配到的
# 例如:
# 我们需要分发所有 video/ 到video视图
# 经过主路由配置的匹配,原本访问 video/667788
# 在分发后的路由中就去除了video/,所以应用中二次匹配就要忽略"video/"
]
3.1路由分发实例
需求任务:
将所有 /App01/* 的路由分发到App01应用中的urls.py的配置中
并且在App01.urls.py配置中配置返回结果
例如:
- 访问 /App01/听歌 -> 返回 “您正在使用app01应用听歌”
- 访问 /App01/买东西 -> 返回 “您正在使用app01买东西”
- 访问 /App01/ -> 返回 “你正在app01,但是啥也没干”
项目主文件夹下的urls.py - project/urls.py
from django.contrib import admin
from django.urls import path,include
import App01.views
urlpatterns = [
path("admin/", admin.site.urls),
re_path("^App01/", include('App01.urls')) # 匹配app01开头,分发到App01.urls
]
App01文件夹下的urls.py - App01/urls.py (需要自己创建)
from django.urls import path, re_path
import App01.views
# App01分发过来的域名是已经去除了分发前的值
# 例如访问 app01/听歌,实际分发过来后已经去除了 "app01/" ,所以在这里仅仅需要匹配后面的听歌就可以了.
urlpatterns = [
re_path("(?P<act>.*/$)", App01.views.active)
]
- 结果示例: -> 访问 /app01/听歌 -> 返回 “您正在使用app01应用听歌”
- 结果示例: -> 访问 /App01/买东西 -> 返回 “您正在使用app01买东西”
- 结果示例: -> 访问 /App01/ -> 返回 “你正在app01,但是啥也没干”
4. 路由命名空间(高级用法,见后续文章)
一般用于反向解析
Django学习-路由反向解析以及命名空间