Django 路由层

1. 路由基础概念

  • URLconf (URL 配置) :Django 的路由系统是基于 urls.py 文件定义的。
  • 路径匹配:通过模式匹配 URL,并将请求传递给对应的视图处理函数。
  • 命名路由:每个路由可以定义一个名称,用于反向解析。

2. 基本路由配置

示例 urls.py 文件

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

urlpatterns = [
    path('', views.home, name='home'),  # 根路径
    path('about/', views.about, name='about'),  # 静态路径
    path('article/<int:id>/', views.article_detail, name='article-detail'),  # 动态参数
]

python 复制代码
# views.py


from django.http import HttpResponse

def home(request):
    return HttpResponse("Welcome to the Home page!")

def about(request):
    return HttpResponse("This is the About page.")

def article_detail(request, id):
    return HttpResponse(f"Article Detail for Article {id}")
  • path() 函数
    • 第一个参数:URL 模式。
    • 第二个参数:对应的视图函数。
    • 第三个参数(可选):name 用于反向解析。

3. 动态路由

动态路由允许在 URL 中传递参数。

示例

python 复制代码
urlpatterns = [
    path('user/<int:user_id>/', views.user_profile, name='user-profile'),  # 整数参数
    path('post/<slug:slug>/', views.post_detail, name='post-detail'),      # 字符串参数
    path('date/<int:year>/<int:month>/', views.archive, name='archive'),   # 多参数
]

python 复制代码
# views.py
from django.http import HttpResponse

def user_profile(request, user_id):
    return HttpResponse(f"User Profile for user {user_id}")

def post_detail(request, slug):
    return HttpResponse(f"Post Detail for post {slug}")

def archive(request, year, month):
    return HttpResponse(f"Archive for {year}-{month}")

支持的路径转换器:

转换器 描述 示例
str 匹配任意非空字符串(默认类型) 'hello/'
int 匹配正整数 '123/'
slug 匹配字母、数字、-_ 'my-post-slug/'
uuid 匹配 UUID 格式 '550e8400-e29b-...'
path 匹配包含 / 的字符串 'some/path/'

4. 子路由与 include

Django 推荐在大型项目中将路由分模块管理。

示例:主路由

python 复制代码
from django.urls import path, include

urlpatterns = [
    path('blog/', include('blog.urls')),  # 引入子路由
    path('shop/', include('shop.urls')),  # 引入另一个应用的路由
]

示例:子路由(blog/urls.py

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

urlpatterns = [
    path('', views.blog_home, name='blog-home'),
    path('<int:post_id>/', views.blog_post, name='blog-post'),
]

python 复制代码
# blog/views.py


from django.http import HttpResponse

def blog_home(request):
    return HttpResponse("Welcome to the blog home page.")

def blog_post(request, post_id):
    return HttpResponse(f"Blog Post with ID {post_id}")

URL /blog//blog/123/ 将分别被子路由处理。


5. 命名空间

在大型项目中,为不同应用的路由定义命名空间,避免路由名称冲突。

主路由配置

python 复制代码
from django.urls import path, include

urlpatterns = [
    path('blog/', include(('blog.urls', 'blog'), namespace='blog')),  # 定义命名空间
]

子路由配置(blog/urls.py

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

app_name = 'blog'  # 命名空间

urlpatterns = [
    path('', views.home, name='home'),
    path('<int:post_id>/', views.post_detail, name='post-detail'),
]

使用反向解析

python 复制代码
from django.urls import reverse

# 使用命名空间解析路由
url = reverse('blog:post-detail', kwargs={'post_id': 1})  # 返回 /blog/1/

6. 正则表达式路由

如果路径匹配需要更复杂的规则,可以使用 re_path,支持正则表达式。

* 示例: 在2.x以上版本 无名分组 有名分组 可以用 re_path 实现

python 复制代码
# urls.py

from django.urls import re_path
from . import views

urlpatterns = [
    
    # 无名分组
    re_path(r'^page/(\d+)/$', views.page_view, name='page-view'),
    
    # 有名分组
    re_path(r'^page/(?P<page_number>\d+)/$', views.page_view, name='page-view'),
]

路径 /page/123/ 会被捕获为 page_number=123


python 复制代码
# views.py


from django.http import HttpResponse

def page_view(request, page_number):
    return HttpResponse(f"Page number: {page_number}")

7. 路由中的默认值

可以为动态路由提供默认值,以减少 URL 的复杂度。

示例

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

urlpatterns = [
    path('profile/<str:username>/', views.profile, name='profile'),
    path('profile/', views.profile, {'username': 'default_user'}, name='default-profile'),
]

请求 /profile/ 将自动解析为 username='default_user'


python 复制代码
# views.py


from django.http import HttpResponse

def profile(request, username='default_user'):
    return HttpResponse(f"User profile: {username}")

8. 类视图的路由

在路由中,可以直接绑定类视图。

示例

python 复制代码
# urls.py


from django.urls import path
from .views import HomeView, ArticleView

urlpatterns = [
    path('', HomeView.as_view(), name='home'),
    path('article/<int:pk>/', ArticleView.as_view(), name='article-detail'),
]

类视图必须使用 .as_view() 方法绑定。


python 复制代码
# views.py


from django.views import View
from django.http import HttpResponse

class HomeView(View):
    def get(self, request):
        return HttpResponse("Welcome to the Home page!")

class ArticleView(View):
    def get(self, request, pk):
        return HttpResponse(f"Article Detail for Article {pk}")

9. 自定义路由转换器

Django 支持自定义路径转换器,用于处理特定格式的路径。

定义自定义转换器

converters.py 中:

python 复制代码
class FourDigitYearConverter:
    regex = r'\d{4}'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return f'{value}'

局部注册转换器

urls.py 中:

python 复制代码
from django.urls import path, register_converter
from .converters import FourDigitYearConverter

register_converter(FourDigitYearConverter, 'yyyy')

urlpatterns = [
    path('year/<yyyy:year>/', views.year_archive, name='year-archive'),
]

请求 /year/2024/ 将解析为 year=2024


* 也可以用继承

导包
python 复制代码
from django.urls.converters import StringConverter


class FourDigitYearConverter(StringConverter):
    regex = r'\d{4}'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return f'{value}'

* 全局注册

python 复制代码
from django.urls.converters import StringConverter, DEFAULT_CONVERTERS


DEFAULT_CONVERTERS['yyyy'] = FourDigitYearConverter

python 复制代码
# views.py


from django.http import HttpResponse

def year_archive(request, year):
    return HttpResponse(f"Year Archive for {year}")

10. 静态文件与媒体文件路由

Django 开发模式下可以通过路由处理静态文件和媒体文件。

配置 settings.py

python 复制代码
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

STATIC_URL = '/static/'
MEDIA_URL = '/media/'

STATICFILES_DIRS = [BASE_DIR / "static"]
MEDIA_ROOT = BASE_DIR / "media"

配置 urls.py

python 复制代码
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # 其他路由
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

总结

Django 路由是通过 urls.py 文件进行管理的,支持以下特性:

  1. 静态和动态路由:支持静态路径和动态参数传递。
  2. 子路由与命名空间:方便模块化管理,避免路由名称冲突。
  3. 反向解析:通过路由名称动态生成 URL。
  4. 自定义转换器:处理自定义路径格式。
  5. 正则表达式路由:支持复杂路径匹配。

路由系统是 Django 项目请求处理的起点,合理设计路由结构能显著提高项目的可维护性

* 11. 前后端反向解析

解析方式 方法 示例代码 解析结果
前端解析 {% url 'route-name' %} <a href="{% url 'about' %}">About</a> /about/
后端解析 reverse('route-name') reverse('about') /about/
动态参数 reverse/{% url %} reverse('article-detail', kwargs={'id': 42}) /article/42/
命名空间 reverse/{% url %} {% url 'blog:post-detail' post_id=5 %} /blog/5/
延迟解析 reverse_lazy reverse_lazy('profile', kwargs={...}) /profile/...
相关推荐
Elastic 中国社区官方博客几秒前
Elasticsearch:Retrievers 介绍
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
蓝桉柒715 分钟前
安装数据库客户端工具
数据库
南城花随雪。42 分钟前
Redis(非关系型数据库)详细介绍
数据库·redis·nosql
冰红茶兑滴水1 小时前
MySQL 内置函数
数据库·mysql
鸿·蒙1 小时前
【PTA】【数据库】【SQL命令】编程题2
数据库·sql·pta
J.P.August1 小时前
Oracle RAC 环境下数据文件误建在本地目录的处理过程
数据库·oracle
对酒当歌丶人生几何1 小时前
Mybatis控制台打印SQL执行信息(执行方法、执行SQL、执行时间)
java·数据库·sql·mybatis
LightOfNight2 小时前
Redis设计与实现第14章 -- 服务器 总结(命令执行器 serverCron函数 初始化)
服务器·数据库·redis·分布式·后端·缓存·中间件
代码中の快捷键2 小时前
MySQL数据库存储引擎的数据结构
数据结构·数据库·mysql