一、Django视图系统详解
1.1 视图基础概念
视图(View)是Django的核心组件之一,负责处理Web请求并返回响应。它可以是一个Python函数(FBV)或一个类(CBV),通常存放在views.py
文件中。
视图的基本职责:
接收HttpRequest对象作为参数
处理业务逻辑
返回HttpResponse对象或其子类
1.2 函数视图(FBV)示例
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = f"<html><body>当前时间: {now}</body></html>"
return HttpResponse(html)
1.3 类视图(CBV)示例
from django.views import View
from django.shortcuts import render, redirect
class AddPress(View):
def get(self, request):
return render(request, 'add_press.html')
def post(self, request):
press_name = request.POST.get('name')
Press.objects.create(name=press_name)
return redirect('/press_list/')
FBV与CBV对比:
类型 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
FBV | 简单直观,适合简单逻辑 | 代码复用性差 | 简单页面、快速开发 |
CBV | 代码复用高,结构清晰 | 学习曲线稍高 | 复杂业务、需要复用逻辑 |
二、Request对象深度解析
2.1 常用Request属性
属性 | 描述 | 示例 |
---|---|---|
request.method |
请求方法(GET/POST等) | if request.method == 'POST': |
request.GET |
GET请求参数(类字典对象) | id = request.GET.get('id') |
request.POST |
POST请求参数(类字典对象) | name = request.POST.get('name') |
request.FILES |
上传的文件对象 | file = request.FILES['file'] |
request.path |
请求路径(不含域名) | /articles/2023/ |
request.META |
请求头信息 | ip = request.META.get('REMOTE_ADDR') |
2.2 常用Request方法
方法 | 描述 | 示例 |
---|---|---|
get_full_path() |
获取完整路径(含查询参数) | /articles/?page=2 |
is_ajax() |
判断是否AJAX请求 | if request.is_ajax(): |
get_host() |
获取请求的主机 | 127.0.0.1:8000 |
2.3 处理多值参数
对于多选框等场景,使用getlist()
获取多个值:
hobbies = request.POST.getlist('hobbies')
三、Response对象全解析
3.1 HttpResponse基础
response = HttpResponse("文本内容", content_type="text/plain")
response.status_code = 200 # 设置状态码
response['X-Custom-Header'] = 'value' # 设置响应头
3.2 常用快捷响应
3.2.1 render() - 渲染模板
from django.shortcuts import render
def my_view(request):
return render(request, 'template.html',
{'data': 'value'},
content_type='text/html',
status=200)
3.2.2 redirect() - 重定向
from django.shortcuts import redirect
def my_view(request):
# 重定向到URL
return redirect('/some/url/')
# 重定向到视图名
return redirect('view_name')
# 重定向到模型(调用get_absolute_url)
return redirect(some_object)
3.2.3 JsonResponse - JSON响应
from django.http import JsonResponse
def my_view(request):
data = {'key': 'value'}
return JsonResponse(data)
# 非字典数据需要设置safe=False
return JsonResponse([1, 2, 3], safe=False)
四、Django路由系统详解
4.1 URL配置基础
基本结构:
from django.urls import path
from . import views
urlpatterns = [
path('articles/2023/', views.special_case_2023),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
]
4.2 路径转换器
Django内置路径转换器:
转换器 | 说明 | 示例 |
---|---|---|
str |
匹配非空字符串(默认) | path('<str:name>/', ...) |
int |
匹配正整数 | path('<int:id>/', ...) |
slug |
匹配字母、数字、连字符 | path('<slug:title>/', ...) |
uuid |
匹配UUID字符串 | path('<uuid:uid>/', ...) |
path |
匹配包含/的字符串 | path('<path:url>/', ...) |
4.3 正则表达式路由
使用re_path
实现复杂匹配:
from django.urls import re_path
urlpatterns = [
re_path(r'articles/(?P<year>[0-9]{4})/$', views.year_archive),
re_path(r'articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
]
4.4 URL命名与反向解析
1. 命名URL:
path('articles/<int:year>/', views.year_archive, name='news-year-archive')
2. 模板中反向解析:
<a href="{% url 'news-year-archive' 2023 %}">2023 Archive</a>
3. Python代码中反向解析:
from django.urls import reverse
reverse('news-year-archive', args=[2023])
4.5 URL命名空间
解决不同app间URL名称冲突问题:
# 主urls.py
path('app01/', include('app01.urls', namespace='app01'))
# 模板中使用
{% url 'app01:view-name' %}
# Python代码中使用
reverse('app01:view-name')
五、实战案例
5.1 综合视图示例
from django.views import View
from django.shortcuts import render, redirect
from django.urls import reverse
from .models import Article
from django.http import JsonResponse
class ArticleView(View):
def get(self, request, article_id):
article = Article.objects.get(id=article_id)
return render(request, 'article_detail.html', {'article': article})
def post(self, request, article_id):
title = request.POST.get('title')
content = request.POST.get('content')
Article.objects.filter(id=article_id).update(
title=title,
content=content
)
return redirect(reverse('article-detail', args=[article_id]))
def delete(self, request, article_id):
Article.objects.filter(id=article_id).delete()
return JsonResponse({'status': 'success'})
5.2 URL配置示例
from django.urls import path, re_path
from . import views
urlpatterns = [
path('articles/', views.ArticleListView.as_view(), name='article-list'),
path('articles/create/', views.ArticleCreateView.as_view(), name='article-create'),
re_path(r'^articles/(?P<pk>[0-9]+)/$',
views.ArticleDetailView.as_view(),
name='article-detail'),
path('api/articles/', views.article_api, name='article-api'),
]
六、高级技巧与最佳实践
6.1 视图装饰器
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods
@login_required
@require_http_methods(["GET", "POST"])
def my_view(request):
# 仅允许已登录用户通过GET或POST方法访问
pass
6.2 自定义路径转换器
# converters.py
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
# urls.py
from django.urls import register_converter, path
from . import converters, views
register_converter(converters.FourDigitYearConverter, 'yyyy')
urlpatterns = [
path('articles/<yyyy:year>/', views.year_archive),
]
6.3 性能优化建议
合理使用select_related/prefetch_related:减少数据库查询
启用缓存:对频繁访问的视图使用缓存
异步处理:耗时操作使用Celery等异步任务队列
分页处理:大数据集使用分页
通过本指南,您应该已经掌握了Django视图和路由系统的核心概念与实用技巧。建议结合官方文档和实际项目练习,以加深理解并提高开发效率。