一、基础视图 (APIView)

APIView 是 DRF 中所有视图的基类,继承自 Django 的 View,并添加了 DRF 特有的功能(如认证、权限、限流等)。

示例:使用APIView实现“增删改查查”

from rest_framework.views import APIView
from rest_framework import serializers
from rest_framework.response import Response
from rest_framework import generics class ShopSerializer(serializers.ModelSerializer):
class Meta:
model = ShopModel
fields = ["id", "username", "title", "description"] class ShopView(APIView):
# 查列表
def get(self, request):
shops = ShopModel.objects.all()
serializer = ShopSerializer(instance=shops, many=True)
return Response(serializer.data) # 增
def post(self, request):
serializer = ShopSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors) class ShopDetailView(APIView):
# 查单个
def get(self, request, pk):
shop = ShopModel.objects.get(pk=pk)
serializer = ShopSerializer(instance=shop)
return Response(serializer.data) # 删
def delete(self, request, pk):
ShopModel.objects.get(pk=pk).delete()
return Response() # 改
def put(self, request, pk):
shop = ShopModel.objects.get(pk=pk)
serializer = ShopSerializer(instance=shop, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors)

配置路由:urls.py

from django.urls import path
from .views import ShopView, ShopDetailView urlpatterns = [
path("shops/", ShopView.as_view()),
path("shops/<int:pk>/", ShopDetailView.as_view()),
]

这种方式虽然直观,但存在大量重复代码(如查询集获取、序列化器实例化等)。为了解决这个问题,DRF 提供了通用视图。

二、通用视图 (Generic Views)

DRF 的通用视图基于 "Mixin 组合" 思想,将常用功能封装成可复用的组件,通过继承组合实现复杂功能。通用视图的核心是 GenericAPIView,它提供了基础的查询集和序列化器管理功能。

常用通用视图

  • ListAPIView:获取列表数据(GET)
  • CreateAPIView:创建数据(POST)
  • RetrieveAPIView:获取单个数据(GET)
  • UpdateAPIView:更新数据(PUT/PATCH)
  • DestroyAPIView:删除数据(DELETE)
  • 组合视图:ListCreateAPIViewRetrieveUpdateAPIView

通用视图示例:学生信息管理

步骤 1:定义模型

# models.py
from django.db import models class Student(models.Model):
name = models.CharField(max_length=255, verbose_name="姓名")
age = models.IntegerField(verbose_name="年龄")
gender = models.CharField(max_length=255, verbose_name="性别") class Meta:
db_table = "student"
verbose_name = "学生表"

步骤 2:创建序列化器

# serializers.py
from rest_framework import serializers
from .models import Student class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = "__all__"

步骤 3:实现通用视图

# views.py
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from .models import Student
from .serializers import StudentSerializer # 查列表、增 视图
class StudentListCreate(ListCreateAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer # 查单个、删、改 视图
class StudentRetrieveUpdateDestroy(RetrieveUpdateDestroyAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer

步骤 4:配置 URL

# urls.py
from django.urls import path
from .views import StudentListCreate, StudentRetrieveUpdateDestroy urlpatterns = [
path("api/students/", StudentListCreate.as_view()),
path("api/students/<int:pk>/", StudentRetrieveUpdateDestroy.as_view()),
]

使用通用视图,实现完整的 CRUD 功能,大大减少了重复代码。

测试通用视图

运行Django项目

# 创建管理员账号
python manage.py createsuperuser --username admin --email admin@example.com
# 运行Django项目
python manage.py runserver 0.0.0.0:8000

打开浏览器登录访问:http://127.0.0.1:8000/api/books/

  • get:查询列表
  • post:新增

打开浏览器登录访问:http://127.0.0.1:8000/api/books/1

  • get:查询单个对象
  • put:修改
  • delete:删除

三、通用视图的高级用法

动态查询集

通过重写 get_queryset() 方法,可以实现动态过滤查询集,例如只返回当前登录用户的数据:

def get_queryset(self):
# 只返回当前用户创建的数据
return Student.objects.filter(created_by=self.request.user)

多字段查询

默认情况下,通用视图通过 pk 字段查询单个对象。如果需要支持多字段查询,可以自定义 Mixin 类:

from django.shortcuts import get_object_or_404

class MultipleFieldLookupMixin:
"""支持多字段查询的 Mixin"""
def get_object(self):
queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
filter_conditions = {}
# 遍历 lookup_fields 构建查询条件
for field in self.lookup_fields:
if self.kwargs.get(field):
filter_conditions[field] = self.kwargs[field]
return get_object_or_404(queryset, **filter_conditions)

使用示例:

class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_fields = ['account', 'username'] # 支持通过 account 或 username 查询

自定义权限和认证

通过设置 permission_classesauthentication_classes 属性,可以为视图添加权限和认证控制:

from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication class UserProfileView(RetrieveAPIView):
serializer_class = UserSerializer
# 只允许已认证用户访问
permission_classes = [IsAuthenticated]
# 使用 Token 认证
authentication_classes = [TokenAuthentication] def get_object(self):
# 返回当前登录用户信息
return self.request.user

四、GenericAPIView类深度解析

GenericAPIView 是 DRF 视图系统的核心抽象,它通过标准化的属性和方法,简化了数据查询、序列化和过滤等常见操作。通过与 Mixin 类结合,GenericAPIView 能够快速实现 CRUD 功能,同时保留了足够的灵活性,允许开发者通过重写方法定制业务逻辑。

类继承关系

GenericAPIView 是 DRF 通用视图体系的基石,其继承关系如下

  • 作为 APIView 的子类,GenericAPIView 保留了请求处理、认证、权限、限流等基础功能
  • GenericAPIView 新增了对查询集(QuerySet)和序列化器(Serializer)的标准化管理,为数据操作提供了统一接口

核心类属性

GenericAPIView 通过类属性定义了视图的核心配置,这些属性决定了视图如何获取数据、如何序列化数据以及如何处理查询参数。

属性名 说明
queryset 视图使用的基础查询集,用于获取模型实例。通常需要设置此属性或重写 get_queryset() 方法。注意直接访问 self.queryset 会导致结果缓存,应优先使用 get_queryset() 方法。
serializer_class 用于数据验证、序列化和反序列化的序列化器类。需设置此属性或重写 get_serializer_class() 方法。
lookup_field 用于查询单个对象的模型字段,默认值为 'pk'(主键)。若使用自定义字段,需确保视图和序列化器同步设置。
lookup_url_kwarg URL 中用于对象查找的关键字参数,默认与 lookup_field 相同。需与 URL 配置中的参数名保持一致。
pagination_class 列表数据的分页类,默认使用全局配置 DEFAULT_PAGINATION_CLASS。设置为 None 可禁用分页。
filter_backends 用于过滤查询集的后端类列表,默认使用全局配置 DEFAULT_FILTER_BACKENDS

常用类方法

GenericAPIView 提供了一系列方法用于处理查询集、对象实例和序列化器,这些方法是构建数据交互逻辑的核心。

数据查询相关方法

  • get_queryset(self):返回视图使用的查询集,是获取数据的主要入口。默认返回 queryset 属性定义的查询集,可重写以实现动态过滤(如返回当前用户的数据)
def get_queryset(self):
return self.request.user.articles.all() # 仅返回当前用户发布的文章
  • get_object(self):返回详细视图所需的单个对象实例。默认通过 lookup_field 从查询集中过滤对象,可重写以实现复杂查询逻辑(如多字段联合查询)。
  • filter_queryset(self, queryset):应用过滤后端对查询集进行过滤,返回处理后的查询集。可通过重写自定义过滤逻辑
def filter_queryset(self, queryset):
# 根据请求参数动态选择过滤后端
if 'category' in self.request.query_params:
queryset = queryset.filter(category=self.request.query_params['category'])
return queryset

序列化器相关方法

  • get_serializer_class(self):返回当前视图使用的序列化器类,默认返回 serializer_class 属性。可重写以根据条件返回不同的序列化器
def get_serializer_class(self):
if self.request.method == 'GET':
return ReadOnlyArticleSerializer # 只读场景使用简化序列化器
return ArticleSerializer # 写操作使用完整序列化器
  • get_serializer(self, instance=None, data=None, many=False, partial=False):返回序列化器实例,自动注入请求上下文(如 request、view)。通常无需重写,直接调用即可
serializer = self.get_serializer(instance=article, data=request.data)

钩子方法(与 Mixin 配合)

GenericAPIView 本身不直接实现 CRUD 操作,而是通过与 Mixin 类(如 CreateModelMixinUpdateModelMixin)结合实现完整功能。这些 Mixin 提供了以下钩子方法,用于定制对象的保存和删除行为

方法名 所属 Mixin 说明
perform_create(self, serializer) CreateModelMixin 创建对象时调用,可用于添加额外字段(如设置创建者): def perform_create(self, serializer): serializer.save(author=self.request.user)
perform_update(self, serializer) UpdateModelMixin 更新对象时调用,可用于记录更新时间等: def perform_update(self, serializer): serializer.save(updated_at=timezone.now())
perform_destroy(self, instance) DestroyModelMixin 删除对象时调用,可用于执行额外清理操作: def perform_destroy(self, instance): instance.comments.all().delete() instance.delete()

其他实用方法

以下方法通常无需重写

  • get_serializer_context(self):返回序列化器的上下文字典,默认包含 requestviewformat 信息,可用于在序列化器中访问请求数据。
  • paginate_queryset(self, queryset):对查询集进行分页处理,返回页面对象或 None(若未配置分页)。
  • get_paginated_response(self, data):返回分页格式的响应对象,配合分页功能使用。

您正在阅读的是《Django从入门到实战》专栏!关注不迷路~

DRF视图详解:从基础视图到通用视图实践指南的更多相关文章

  1. (转)oracle视图详解

    Oracle视图详解   一. 视图的定义 视图(view),也称虚表, 不占用物理空间,这个也是相对概念,因为视图本身的定义语句还是要存储在数据字典里的.视图只有逻辑定义.每次使用的时候,只是重新执 ...

  2. ASP.NET MVC 5 学习教程:Edit方法和Edit视图详解

    原文 ASP.NET MVC 5 学习教程:Edit方法和Edit视图详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 ...

  3. 【译】ASP.NET MVC 5 教程 - 7:Edit方法和Edit视图详解

    原文:[译]ASP.NET MVC 5 教程 - 7:Edit方法和Edit视图详解 在本节中,我们继续研究生成的Edit方法和视图.但在研究之前,我们先将 release date 弄得好看一点.打 ...

  4. [转]PostgreSQL教程(十六):系统视图详解

    这篇文章主要介绍了PostgreSQL教程(十六):系统视图详解,本文讲解了pg_tables.pg_indexes.pg_views.pg_user.pg_roles.pg_rules.pg_set ...

  5. Linux dts 设备树详解(一) 基础知识

    Linux dts 设备树详解(一) 基础知识 Linux dts 设备树详解(二) 动手编写设备树dts 文章目录 1 前言 2 概念 2.1 什么是设备树 dts(device tree)? 2. ...

  6. calcite物化视图详解

    概述 物化视图和视图类似,反映的是某个查询的结果,但是和视图仅保存SQL定义不同,物化视图本身会存储数据,因此是物化了的视图. 当用户查询的时候,原先创建的物化视图会注册到优化器中,用户的查询命中物化 ...

  7. 使用Material Design Tint和视图详解

    视图 首先来讲Material Design 视图的概念,在新的api中,新添加了z轴的概念,z轴垂直于屏幕,用来表现元素的层叠关系,z值(海拔高度)越高,元素离界面底层(水平面)越远,投影越重,这里 ...

  8. Oracle视图详解

    转载自:http://blog.itpub.net/29785807/viewspace-1270120/ 一. 视图的定义 视图(view),也称虚表, 不占用物理空间,这个也是相对概念,因为视图本 ...

  9. Oracle物化视图详解

    现实工作中会有多个数据源同步到一个数据库完成数据分析的场景,这些数据可以不是实时同步的,我们一般通过定时任务抽取数据到统计分析库给应用使用. 一般的同步方式可以通过时间戳做全量和增量数据同步(存在原数 ...

  10. Django(十一)视图详解:基本使用、登录实例、HttpReqeust对象、HttpResponse对象

    一.视图(基于类的视图) [参考]https://docs.djangoproject.com/zh-hans/3.0/topics/class-based-views/intro/ 1)视图的功能 ...

随机推荐

  1. WPF 的 await Application.Current.Dispatcher.InvokeAsync,Func 如果是Task , 等待赋值可能存在没有等待执行完成的问题

    最近在检查我们组内的代码,发现好多用到 await Application.Current.Dispatcher.InvokeAsync 相信好多WPF的开发都会用到 该方法做UI线程切换.但是细看里 ...

  2. WPF 使用GDI+提取图片主色调并生成Mica材质特效背景

    先看效果,在浅色模式下: 在深色模式下: P.S. 此算法只是尽可能地接近Windows Mica效果,并非实际实现:主色调提取算法只能确保在绝大多数情况下适用. 测试项目在Github上开源: Tw ...

  3. java返回数据库中层级结构数据的treeListMap写法,以动态菜单为例

    说明 1.treeListMap写法,与纯算法版本比起来,treeListMap版的缺点是会查询多次数据库,而纯算法只会查询一次数据库 2.里面有不同角色分配不同的菜单相关代码,注意复制粘贴. 3.可 ...

  4. Ingress学习笔记

    Ingress 我们已经知道,Service对集群之外暴露服务的主要方式有两种:NodePort和LoadBalancer,但是这两种方式,都有一定的缺点: NodePort方式的缺点是会占用很多集群 ...

  5. 手把手教你网络爬虫(爬取豆瓣电影top250,附带源代码)

    概念 网络爬虫就是按照一定的规则,自动抓取互联网信息的程序或脚本.其本质就是模拟浏览器打开网页,获取网页中我们需要的数据. 基本流程 准备工作(构建流程) 获取数据 解析内容 保存数据 1. 准备工作 ...

  6. go 进阶训练营 微服务可用性(下)笔记

    降级: 减少工作量,丢弃不重要的请求. 确定具体采用哪个指标作为流量评估和优雅降级的决定性指标: 如 CPU.延迟.队列长度.线程数量.错误等 当服务进入降级时,需要执行什么动作? 流量抛弃或者优雅降 ...

  7. 利用python、scipy求解差分方程的解

    文档:https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lfilter.html#scipy.signal.lfilt ...

  8. 学习php,整了一个php小马:无用小马项目介绍

    主要实现了几个功能:1.嗅探文件.可以嗅探服务器上的文件 2.大马上传.可以拿来传大马,既可以选择直接上传文件,也可以选择保存到小马上传地址. 3.打算还加一些好用的功能,比如说修改php.ini之类 ...

  9. 探索学习Hypermesh的有效方法

    大家好!我是一名Hypermesh的学习者,最近在学习这个强大的有限元前处理软件时,总结了一些有效的学习方法,希望能与大家分享. 1. 熟悉软件界面和工具:首先,我们需要熟悉Hypermesh的界面和 ...

  10. Blazor学习之旅(12) JavaScript与Blazor的互操作

    大家好,我是Edison. 在上一篇我们学习了Blazor+SignalR开发简单的实时应用程序,这一篇我们了解下Blazor和JavaScript的互操作性. 有了Blazor还需要JavaScri ...