一、基础视图 (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)
- 组合视图:ListCreateAPIView、RetrieveUpdateAPIView 等
通用视图示例:学生信息管理
步骤 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/
打开浏览器登录访问: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_classes 和 authentication_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_kwargURL 中用于对象查找的关键字参数,默认与 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 类(如 CreateModelMixin、UpdateModelMixin)结合实现完整功能。这些 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):返回序列化器的上下文字典,默认包含 request、view、format 信息,可用于在序列化器中访问请求数据。
- paginate_queryset(self, queryset):对查询集进行分页处理,返回页面对象或 None(若未配置分页)。
- get_paginated_response(self, data):返回分页格式的响应对象,配合分页功能使用。
您正在阅读的是《Django从入门到实战》专栏!关注不迷路~
来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除 |