#Django View视图层详解
#课程目标
- 理解Django视图的概念和作用
- 掌握函数视图和类视图的使用
- 学会处理HTTP请求和响应
- 了解Django的URL配置机制
#视图简介
Django视图是处理HTTP请求并返回HTTP响应的函数或类。视图位于Django MTV架构的"V"层(View),负责处理业务逻辑并返回响应给用户。
#视图的职责:
- 接收HTTP请求
- 处理业务逻辑
- 返回HTTP响应
#函数视图(Function-Based Views)
#基本函数视图
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)#使用模板的函数视图
from django.shortcuts import render
from django.http import HttpResponse
def article_list(request):
articles = Article.objects.all()
context = {'articles': articles}
return render(request, 'articles/list.html', context)#处理POST请求
from django.shortcuts import render, redirect
from django.contrib import messages
def create_article(request):
if request.method == 'POST':
title = request.POST.get('title')
content = request.POST.get('content')
# 保存到数据库
article = Article.objects.create(
title=title,
content=content,
author=request.user
)
messages.success(request, '文章创建成功!')
return redirect('article_detail', id=article.id)
return render(request, 'articles/create.html')#类视图(Class-Based Views)
#基本类视图
from django.views import View
from django.http import HttpResponse
class HelloView(View):
def get(self, request):
return HttpResponse('Hello, World!')
def post(self, request):
return HttpResponse('Received POST request')#通用视图
from django.views.generic import ListView, DetailView, CreateView
from django.urls import reverse_lazy
class ArticleListView(ListView):
model = Article
template_name = 'articles/list.html'
context_object_name = 'articles'
paginate_by = 10
def get_queryset(self):
return Article.objects.filter(is_published=True)
class ArticleDetailView(DetailView):
model = Article
template_name = 'articles/detail.html'
context_object_name = 'article'
class ArticleCreateView(CreateView):
model = Article
fields = ['title', 'content', 'category']
template_name = 'articles/create.html'
success_url = reverse_lazy('article_list')#HTTP请求处理
#请求对象属性
def handle_request(request):
# 请求方法
method = request.method
# GET参数
search = request.GET.get('search', '')
# POST数据
username = request.POST.get('username', '')
# 请求头
user_agent = request.META.get('HTTP_USER_AGENT', '')
# 用户信息
user = request.user
# 会话信息
session_data = request.session.get('key', 'default')
# IP地址
ip_address = request.META.get('REMOTE_ADDR', '')#请求方法处理
def article_manage(request, article_id):
try:
article = Article.objects.get(id=article_id)
except Article.DoesNotExist:
return HttpResponse('文章不存在', status=404)
if request.method == 'GET':
# 显示文章详情
context = {'article': article}
return render(request, 'articles/detail.html', context)
elif request.method == 'POST':
# 更新文章
article.title = request.POST.get('title')
article.content = request.POST.get('content')
article.save()
return redirect('article_detail', id=article.id)
elif request.method == 'DELETE':
# 删除文章
article.delete()
return HttpResponse('删除成功')
else:
return HttpResponse('不支持的请求方法', status=405)#响应处理
#基本响应
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
from django.shortcuts import redirect
def basic_responses(request):
# 简单响应
response = HttpResponse("Hello, World!")
# JSON响应
data = {'status': 'success', 'message': '操作成功'}
return JsonResponse(data)
# 重定向
return redirect('/home/')
# 或者
return HttpResponseRedirect('/home/')#模板响应
from django.shortcuts import render, get_object_or_404
def article_detail(request, article_id):
# 使用get_object_or_404自动处理不存在的情况
article = get_object_or_404(Article, id=article_id)
context = {
'article': article,
'comments': article.comments.all(),
}
return render(request, 'articles/detail.html', context)#URL配置
#URL模式定义
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('articles/', views.ArticleListView.as_view(), name='article_list'),
path('articles/<int:article_id>/', views.article_detail, name='article_detail'),
path('articles/create/', views.ArticleCreateView.as_view(), name='article_create'),
path('articles/<int:pk>/edit/', views.ArticleUpdateView.as_view(), name='article_update'),
path('articles/<int:pk>/delete/', views.ArticleDeleteView.as_view(), name='article_delete'),
]#URL参数传递
# 在urls.py中定义带参数的URL
path('articles/<int:article_id>/', views.article_detail, name='article_detail'),
path('articles/<slug:slug>/', views.article_by_slug, name='article_by_slug'),
path('articles/<int:year>/<int:month>/', views.articles_by_date, name='articles_by_date'),
# 在视图中接收参数
def article_detail(request, article_id):
article = get_object_or_404(Article, id=article_id)
return render(request, 'articles/detail.html', {'article': article})
def articles_by_date(request, year, month):
articles = Article.objects.filter(
pub_date__year=year,
pub_date__month=month
)
return render(request, 'articles/list.html', {'articles': articles})#装饰器使用
#常用装饰器
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods, require_GET, require_POST
from django.views.decorators.csrf import csrf_exempt
@login_required
def protected_view(request):
"""需要登录才能访问"""
return render(request, 'protected.html')
@require_POST
def create_article(request):
"""只接受POST请求"""
# 处理创建逻辑
pass
@csrf_exempt
def webhook_view(request):
"""免除CSRF检查"""
# Webhook处理逻辑
pass#错误处理
#自定义错误页面
# views.py
def custom_404(request, exception):
return render(request, 'errors/404.html', status=404)
def custom_500(request):
return render(request, 'errors/500.html', status=500)
# 在urls.py中配置
handler404 = 'myapp.views.custom_404'
handler500 = 'myapp.views.custom_500'#视图最佳实践
#视图组织原则
- 保持视图函数简洁,将复杂逻辑移到模型或服务层
- 合理使用通用视图减少重复代码
- 正确处理异常和错误情况
- 使用适当的HTTP状态码
#示例:良好实践的视图
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db import transaction
@login_required
@transaction.atomic
def update_article(request, article_id):
article = get_object_or_404(Article, id=article_id)
# 检查权限
if article.author != request.user:
messages.error(request, '您没有权限编辑这篇文章')
return redirect('article_detail', id=article.id)
if request.method == 'POST':
try:
article.title = request.POST.get('title', '').strip()
article.content = request.POST.get('content', '')
if not article.title:
messages.error(request, '标题不能为空')
return render(request, 'articles/edit.html', {'article': article})
article.save()
messages.success(request, '文章更新成功')
return redirect('article_detail', id=article.id)
except Exception as e:
messages.error(request, f'更新失败:{str(e)}')
return render(request, 'articles/edit.html', {'article': article})#课程总结
本节课我们学习了Django的视图层,包括函数视图和类视图的使用、HTTP请求和响应的处理、URL配置等内容。视图是Django应用的核心组成部分,掌握视图的使用对构建Web应用至关重要。

