Bootstrap

Django 路由层

1. 路由基础概念

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

2. 基本路由配置

示例 urls.py 文件

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'),  # 动态参数
]



# 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 中传递参数。

示例

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'),   # 多参数
]



# 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 推荐在大型项目中将路由分模块管理。

示例:主路由

from django.urls import path, include

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


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

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'),
]



# 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. 命名空间

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

主路由配置

from django.urls import path, include

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


子路由配置(blog/urls.py

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'),
]

使用反向解析

from django.urls import reverse

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

6. 正则表达式路由

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

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

# 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


# views.py


from django.http import HttpResponse

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



7. 路由中的默认值

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

示例

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'


# views.py


from django.http import HttpResponse

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



8. 类视图的路由

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

示例

# 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() 方法绑定。


# 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 中:

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

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

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

局部注册转换器

urls.py 中:

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


 * 也可以用继承

导包

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}'



 * 全局注册

from django.urls.converters import StringConverter, DEFAULT_CONVERTERS


DEFAULT_CONVERTERS['yyyy'] = FourDigitYearConverter



# views.py


from django.http import HttpResponse

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



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

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

配置 settings.py

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

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_lazyreverse_lazy('profile', kwargs={...})/profile/...
;