1. 路由基础概念
- URLconf (URL 配置):Django 的路由系统是基于
urls.py
文件定义的。 - 路径匹配:通过模式匹配 URL,并将请求传递给对应的视图处理函数。
- 命名路由:每个路由可以定义一个名称,用于反向解析。
2. 基本路由配置
示例 urls.py
文件
from django.urls import path
from . import viewsurlpatterns = [path('', views.home, name='home'), # 根路径path('about/', views.about, name='about'), # 静态路径path('article/<int:id>/', views.article_detail, name='article-detail'), # 动态参数
]
# views.pyfrom django.http import HttpResponsedef 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 HttpResponsedef 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, includeurlpatterns = [path('blog/', include('blog.urls')), # 引入子路由path('shop/', include('shop.urls')), # 引入另一个应用的路由
]
示例:子路由(blog/urls.py
)
from django.urls import path
from . import viewsurlpatterns = [path('', views.blog_home, name='blog-home'),path('<int:post_id>/', views.blog_post, name='blog-post'),
]
# blog/views.pyfrom django.http import HttpResponsedef 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, includeurlpatterns = [path('blog/', include(('blog.urls', 'blog'), namespace='blog')), # 定义命名空间
]
子路由配置(blog/urls.py
)
from django.urls import path
from . import viewsapp_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.pyfrom django.urls import re_path
from . import viewsurlpatterns = [# 无名分组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.pyfrom django.http import HttpResponsedef page_view(request, page_number):return HttpResponse(f"Page number: {page_number}")
7. 路由中的默认值
可以为动态路由提供默认值,以减少 URL 的复杂度。
示例
from django.urls import path
from . import viewsurlpatterns = [path('profile/<str:username>/', views.profile, name='profile'),path('profile/', views.profile, {'username': 'default_user'}, name='default-profile'),
]
请求 /profile/
将自动解析为 username='default_user'
。
# views.pyfrom django.http import HttpResponsedef profile(request, username='default_user'):return HttpResponse(f"User profile: {username}")
8. 类视图的路由
在路由中,可以直接绑定类视图。
示例
# urls.pyfrom django.urls import path
from .views import HomeView, ArticleViewurlpatterns = [path('', HomeView.as_view(), name='home'),path('article/<int:pk>/', ArticleView.as_view(), name='article-detail'),
]
类视图必须使用 .as_view()
方法绑定。
# views.pyfrom django.views import View
from django.http import HttpResponseclass 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 FourDigitYearConverterregister_converter(FourDigitYearConverter, 'yyyy')urlpatterns = [path('year/<yyyy:year>/', views.year_archive, name='year-archive'),
]
请求 /year/2024/
将解析为 year=2024
。
* 也可以用继承
导包
from django.urls.converters import StringConverterclass 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_CONVERTERSDEFAULT_CONVERTERS['yyyy'] = FourDigitYearConverter
# views.pyfrom django.http import HttpResponsedef year_archive(request, year):return HttpResponse(f"Year Archive for {year}")
10. 静态文件与媒体文件路由
Django 开发模式下可以通过路由处理静态文件和媒体文件。
配置 settings.py
from pathlib import PathBASE_DIR = Path(__file__).resolve().parent.parentSTATIC_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 staticurlpatterns = [# 其他路由
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
总结
Django 路由是通过 urls.py
文件进行管理的,支持以下特性:
- 静态和动态路由:支持静态路径和动态参数传递。
- 子路由与命名空间:方便模块化管理,避免路由名称冲突。
- 反向解析:通过路由名称动态生成 URL。
- 自定义转换器:处理自定义路径格式。
- 正则表达式路由:支持复杂路径匹配。
路由系统是 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/... |