django View视图层详解

课程目标

  • 理解django视图的概念和作用
  • 掌握函数视图和类视图的使用
  • 学会处理HTTP请求和响应
  • 了解django的URL配置机制

视图简介

django视图是处理HTTP请求并返回HTTP响应的函数或类,位于django MTV架构的"V"层(View),是连接用户输入、业务逻辑、页面展示的核心纽带。

视图的核心职责:

  1. 接收并解析浏览器发来的HTTP请求
  2. 调用模型层、服务层处理业务逻辑(如数据增删改查)
  3. 生成符合要求的HTTP响应返回给浏览器

函数视图(Function-Based Views)

函数视图是django最早也是最直观的视图形式——一个Python函数对应一个URL路由,适合逻辑简单或高度自定义的场景。

基础无模板视图

直接返回HTML字符串或纯文本,适合调试或极简接口:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    # request是django自动传入的HttpRequest对象,包含所有请求信息
    now = datetime.datetime.now()
    html = f"<html><body>现在是 {now.strftime('%Y-%m-%d %H:%M:%S')}</body></html>"
    return HttpResponse(html)

结合模板的视图

django.shortcuts.render快速渲染HTML模板(MTV架构的核心体现,把视图逻辑和页面展示分离):

from django.shortcuts import render

# 假设已定义好Article模型
def article_list(request):
    articles = Article.objects.filter(is_published=True).order_by("-pub_date")[:10]
    # context字典用于向模板传递变量
    context = {"articles": articles}
    return render(request, "articles/list.html", context)

处理表单POST请求

通过request.method区分请求类型,配合messages框架和redirect实现完整的表单流程:

from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required

@login_required  # 强制登录
def create_article(request):
    if request.method == "POST":
        # 获取POST表单数据(get的第二个参数是默认值)
        title = request.POST.get("title", "").strip()
        content = request.POST.get("content", "").strip()
        
        if not title or not content:
            messages.error(request, "标题和内容不能为空")
            return render(request, "articles/create.html")
        
        # 保存到数据库
        Article.objects.create(
            title=title,
            content=content,
            author=request.user,
            is_published=True
        )
        
        messages.success(request, "文章发布成功!")
        # 重定向到列表页(避免表单重复提交)
        return redirect("article_list")
    
    # GET请求直接返回空表单
    return render(request, "articles/create.html")

类视图(Class-Based Views)

类视图用面向对象的方式组织代码,自带很多通用场景的封装,可以大幅减少重复代码,适合CRUD(增删改查)、分页等标准化场景。

基础View类视图

继承django.views.View,通过重写HTTP方法名对应的函数(如get()post())处理请求:

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

class HelloView(View):
    def get(self, request):
        return HttpResponse("Hello, Class-Based Views!")
    
    def post(self, request):
        return HttpResponse("Received POST from CBV")

通用视图(Generic Views)

django内置了一套封装好的通用类视图,直接覆盖属性或轻量重写方法即可使用:

from django.views.generic import ListView, DetailView, CreateView
from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin

class ArticleListView(ListView):
    model = Article  # 指定操作的模型
    template_name = "articles/list.html"  # 指定渲染的模板
    context_object_name = "articles"  # 指定传递给模板的变量名(默认是object_list)
    paginate_by = 10  # 开启分页,每页10条
    
    # 重写get_queryset自定义查询条件(默认是model.objects.all())
    def get_queryset(self):
        return Article.objects.filter(is_published=True).order_by("-pub_date")

class ArticleDetailView(DetailView):
    model = Article
    template_name = "articles/detail.html"
    context_object_name = "article"
    pk_url_kwarg = "article_id"  # 指定URL参数名(默认是pk)

# LoginRequiredMixin放在前面,强制类视图登录
class ArticleCreateView(LoginRequiredMixin, CreateView):
    model = Article
    fields = ["title", "content", "category"]  # 指定表单字段
    template_name = "articles/create.html"
    success_url = reverse_lazy("article_list")  # 成功后跳转的URL(reverse_lazy适合类视图延迟解析)
    
    # 重写form_valid自定义保存逻辑(默认只保存表单字段)
    def form_valid(self, form):
        form.instance.author = self.request.user
        form.instance.is_published = True
        return super().form_valid(form)

HTTP请求与响应处理

django封装了完整的HttpRequest(请求)和HttpResponse(响应)体系,我们只需要操作这两个对象即可。

HttpRequest常用属性

def handle_request(request):
    # 请求方法:GET/POST/PUT/DELETE等
    method = request.method
    
    # GET查询参数(如?search=python)
    search_keyword = request.GET.get("search", "")
    
    # POST表单数据
    username = request.POST.get("username", "")
    
    # 请求头信息(注意HTTP前缀,且转成大写加下划线)
    user_agent = request.META.get("HTTP_USER_AGENT", "未知浏览器")
    client_ip = request.META.get("REMOTE_ADDR", "")
    
    # 用户与会话信息(需启用Auth和Session中间件)
    is_logged_in = request.user.is_authenticated
    cart_count = request.session.get("cart_count", 0)

常用HttpResponse子类

from django.http import (
    HttpResponse,
    JsonResponse,
    HttpResponseRedirect,
    HttpResponseNotFound
)
from django.shortcuts import redirect, get_object_or_404

def response_demo(request):
    # 1. 纯文本/HTML响应
    text_resp = HttpResponse("这是纯文本响应")
    html_resp = HttpResponse("<h1>这是HTML响应</h1>", content_type="text/html")
    
    # 2. JSON响应(自动设置content_type为application/json,且safe=False允许非字典类型)
    json_resp = JsonResponse({"status": "success", "data": [1,2,3]}, safe=False)
    
    # 3. 重定向响应(推荐用redirect快捷函数,支持URL名称和对象)
    redirect_by_name = redirect("article_list")
    redirect_by_obj = redirect(Article.objects.first())
    redirect_raw = HttpResponseRedirect("/articles/")
    
    # 4. 404响应(推荐用get_object_or_404快捷函数自动触发)
    article = get_object_or_404(Article, id=999)
    manual_404 = HttpResponseNotFound("页面走丢了")

URL配置机制

django通过URLconf模块(通常是项目的urls.py和各应用的urls.py)把URL路径映射到对应的视图。

基础URL模式

# 项目的根urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),  # 管理后台
    path("articles/", include("articles.urls")),  # 包含应用的子路由
]
# articles应用的子urls.py
from django.urls import path
from . import views

urlpatterns = [
    # 函数视图映射
    path("", views.article_list, name="article_list"),
    path("<int:article_id>/", views.article_detail, name="article_detail"),
    # 类视图映射(必须调用.as_view()方法)
    path("create/", views.ArticleCreateView.as_view(), name="article_create"),
]

URL参数类型

django内置了几种常用的路径转换器:

  • <int:id>:匹配整数
  • <slug:slug>:匹配slug字符串(字母、数字、下划线、连字符)
  • <str:title>:匹配除路径分隔符/外的所有字符串(默认类型)
  • <uuid:uuid>:匹配UUID
  • <path:path>:匹配包含路径分隔符/的所有字符串

装饰器与最佳实践

常用视图装饰器

装饰器可以快速给视图添加额外功能,函数视图直接用@装饰器,类视图用method_decorator或混入(Mixin):

from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods, require_POST
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

# 函数视图装饰器
@login_required
@require_POST
def delete_article(request, article_id):
    # 处理删除逻辑
    pass

@csrf_exempt  # 仅用于第三方Webhook等无需CSRF的场景
def wechat_webhook(request):
    # 处理微信回调
    pass

# 类视图装饰器(用method_decorator)
@method_decorator(login_required, name="dispatch")
class ArticleUpdateView(View):
    def get(self, request):
        pass

视图最佳实践

  1. 保持视图简洁:复杂的业务逻辑移到模型层的方法、或独立的服务层
  2. 合理使用通用视图:CRUD、分页等场景优先用通用类视图
  3. 正确处理异常:用get_object_or_404get_list_or_404替代手动抛出404
  4. 避免表单重复提交:POST请求处理成功后必须重定向(PRG模式)
  5. 使用适当的状态码:如403(权限不足)、405(方法不允许)、201(创建成功)

课程总结

本节课我们系统学习了django视图层的核心内容:

  • 视图的概念和职责
  • 函数视图的基础、模板、表单处理
  • 类视图的基础、通用类视图(CRUD、分页等)
  • HttpRequest和HttpResponse的常用操作
  • URLconf的配置和路径转换器
  • 常用装饰器和视图最佳实践

视图是django应用的核心入口,掌握视图的使用对构建任何Web应用都至关重要。下节课我们将学习django的模板层!