前言
主要介绍了Django REST framework中,GenericAPIView的与混入类、扩展类的概念、功能和使用方法,最后通过代码示例逐步演示了从GenericAPIView到GenericAPIView结合混入类再到扩展类、视图集的封装流程及其操作。
一、GenericAPIView
1. GenericAPIView是什么
GenericAPIView
继承自APIVIew
,增加了对于 列表视图 和 详情视图 可能用到的 通用支持方法,通常使用时,可搭配一个或多个Mixin
扩展类,来实现其他更加高级的功能,总结来说GenericAPIView
是有关数据管理的基类,未来还会学习有关方法操作的基类导入GenericAPIView:
from rest_framework.generics import GenericAPIView
2. GenericAPIView内部属性
🔥列表、详情视图通用属性:
- queryset=
objects.all
/.filter
/.order_by
- 列表视图要操作的查询结果对象
- serializer_class=
Serializer
- 视图中会使用到的 序列化器,一般都是针对于上一个 queryset 所指定的
列表视图单独属性:
- pagination_class
- 分页控制类,进行分页设置
- filter_backends
- 过滤控制后端,可以对数据进行字段过滤
🔥详情页视图单独属性:
- lookup_url_kwarg
- 动态路由传递的参数命名
- lookup_field
- 过滤的orm参数
🔥列表与详情视图通用方法:
- get_queryset(self)
- 返回视图使用的查询集,是列表视图与详情视图获取数据的基础
- 默认返回queryset属性,支持重写
- get_serializer_class(self)
- 返回序列化器类,默认返回serializer_class,可以重写
- get_serializer(self, args, kwargs)
- 返回序列化器对象
🔥详情页视图单独方法:
- get_object(self)
- 返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象
- 若详情访问的模型类对象不存在,会返回404,如果访问到多个重复,也会报错,默认使用get方法进行orm查询
- 该方法会默认使用 APIView 提供的check_object_permissions方法检查当前对象是否有权限被访问
3. GenericAPIView增删改查
1. 获取数据与添加数据:
编写UserGenView视图类,urls.py路由,代码如下:
# views.py from rest_framework.response import Response from app.models import UserModel from app.serializer.userSerializer import UserSerializer from rest_framework.generics import GenericAPIView class UserGenView(GenericAPIView): queryset = UserModel.objects.all() serializer_class = UserSerializer lookup_field = 'pk' lookup_url_kwarg = 'id' def get(self, request): users = self.get_queryset() # <==> UserModel.objects.all() ser = self.get_serializer(instance=users, many=True) return Response({"userList": ser.data}) def post(self, request): ser = self.get_serializer(data=request.data) if ser.is_valid(): print("校验成功!") ser.save() return Response({"user": ser.data}) else: return Response({"error": ser.errors}) #-------------------------------------------------------------- #urls.py from django.urls import path from app.views import UserView,UserIdView,UserGenView,UserGenIDView urlpatterns = [ path('user/', UserView.as_view()), path('user/<int:id>/', UserIdView.as_view()), path('usgns/', UserGenView.as_view()), ]
2. GenericAPIView 增删改查 (传id)
UserGenIDView模型类和urls.py路由 代码如下:
#views.py from rest_framework.response import Response from app.models import UserModel from app.serializer.userSerializer import UserSerializer from rest_framework.generics import GenericAPIView # Create your views here. class UserGenIDView(GenericAPIView): queryset = UserModel.objects.all() serializer_class = UserSerializer lookup_field = 'pk' #指向数据库,查询key lookup_url_kwarg = 'id' # url 路径中的参数名 def get(self, request, id): user = self.get_object() ser = self.get_serializer(instance=user) return Response({"message": "查询成功!","data":ser.data}) def put(self, request, id): user = self.get_object() ser = self.get_serializer(instance=user, data=request.data) if ser.is_valid(): ser.save() return Response({"message": "success"}) else: return Response({"message": ser.errors}) def delete(self, request, id): self.get_object().delete() return Response({"message":"删除成功!"}) #------------------------------------------------- #urls.py from django.urls import path from app.views import UserView,UserIdView,UserGenView,UserGenIDView urlpatterns = [ path('user/', UserView.as_view()), path('user/<int:id>/', UserIdView.as_view()), path('usgns/', UserGenView.as_view()), path('usgns/<int:id>/', UserGenIDView.as_view()), ]
二、混入类与扩展类
在
Django REST framework (DRF)
中,混入扩展类(Mixin Extension Classes)
是一种特殊的类,它们封装了特定功能的代码片段,这些功能通常与数据库操作(如增删改查)相关。混入扩展类(通常称为Mixin 类
)不是独立的视图类,而是用于与通用视图基类(如GenericAPIView
)结合使用,以提供额外的功能。
GenericAPIView
只是提供了数据,对应的访问功能是没有实现的,所以DRF还有五个提供方法的混入类,可以完成基本增删改查功能,我们也叫Mixin 混入类,通过GenericAPIView与混入类的多继承,可以实现更加复杂的接口功能,GenericAPIView提供数据,而混入类提供操作导包:
from rest_framework.mixins import CreateModelMixin,ListModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
1. 混入类的功能划分
1. ListModelMixin
- 列表视图扩展类,提供
list(request, *args, **kwargs)
方法快速实现列表视图- 默认返回200状态码
- 该Mixin的 list 方法会对数据进行过滤和分页
2. CreateModelMixin
- 创建视图扩展类,提供
create(request, *args, **kwargs)
方法快速实现创建资源的视图- 成功返回201状态码。
- 如果序列化器对前端发送的数据验证失败,返回 400错误
3. RetrieveModelMixin
- 详情视图扩展类,提供
retrieve(request, *args, **kwargs)
方法进行单独数据的返回- 如果详情数据存在,返回200, 否则返回404
4. UpdateModelMixin
- 更新视图扩展类,提供
update(request, *args, **kwargs)
方法- 同时提供
partial_update(request, *args, **kwargs)
方法,可以实现局部更新。- 成功返回200,序列化器校验数据失败时,返回400错误
5. DestroyModelMixin
- 删除视图扩展类,提供
destroy(request, *args, **kwargs)
方法- 可以快速实现删除一个存在的数据对象
- 成功返回204,不存在返回404
2. 混入类与GenericAPIView的组合使用(增删改查操作)
查询所有,增加数据,(未传 参数 id)代码示例如下:
# views_mixin.py from rest_framework.generics import GenericAPIView from rest_framework.response import Response from app.models import UserModel from app.serializer.userSerializer import UserSerializer from rest_framework.mixins import ListModelMixin,CreateModelMixin class UserMixinView(GenericAPIView, ListModelMixin,CreateModelMixin): # GenericAPIView 对数据提供进行了封装 queryset = UserModel.objects.all() serializer_class = UserSerializer def get(self, request): # PS:可以点进ListModelMixin中与list()方法对比,list()方法已经对下面两行代码实现过封装了 # 获取所有信息,并进行序列化返回 # users = self.get_queryset() # ser = self.get_serializer(instance=users, many=True) # return Response({"message":"Hello GET","data":ser.data}) return self.list(request) def post(self, request): # PS:可以点进CreateModelMixin中与create()方法对比, # create()方法已经对手动使用post方法新增数据封装过了 return self.create(request)
查,改,删(传参数 id),代码示例如下:
# views_mixin.py from rest_framework.generics import GenericAPIView from rest_framework.response import Response from app.models import UserModel from app.serializer.userSerializer import UserSerializer from rest_framework.mixins import RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin class UserMixinIDView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin): # GenericAPIView 对数据提供进行了封装 queryset = UserModel.objects.all() serializer_class = UserSerializer lookup_field = 'pk' lookup_url_kwarg = 'id' def get(self, request, id): return self.retrieve(request) def put(self, request, id): return self.update(request) def delete(self, request, id): return self.destroy(request)
urls.py:
from django.urls import path from app.views_mixin import UserMixinView,UserMixinIDView urlpatterns = [ path('usmixin/', UserMixinView.as_view()), path('usmixin/<int:id>', UserMixinIDView.as_view()), ]
3. 视图扩展类的应用
在
Django REST framework (DRF)
中,视图扩展类(View Extensions or Generic View Classes)是一组内置的类,它们为构建RESTful API
提供了强大的基础。这些扩展类允许开发者以声明式的方式定义视图的行为,从而简化了 API 开发的复杂性。这些类结合了
Mixin 类
的功能,并提供了额外的逻辑(如请求处理、权限检查、序列化等)。通用视图类可以直接作为 API 视图使用。一些常见的通用视图类包括:
ListAPIView
:列出查询集中的对象。CreateAPIView
:创建并保存一个模型实例。RetrieveAPIView
:根据提供的查找字段检索并返回对象。UpdateAPIView
:更新一个现有的模型实例。DestroyAPIView
:删除一个现有的模型实例。
1. ListAPIView
- 提供get方法,可以获取多条数据
继承自:GenericAPIView、ListModelMixin
class TeacherListView(ListAPIView): queryset = Teacher.objects.all() # 你要序列化的哪些数据结果 serializer_class = TeacherListSer # 用什么序列化器
2. CreateAPIView
- 提供post方法,可以创建一条数据
继承自:GenericAPIView、CreateModelMixin
class TeacherCreateView(CreateAPIView): serializer_class = TeacherCreateSer
3. RetireveAPIView
- 提供get方法,获取某个具体数据的详情
继承自:GenericAPIView、RetrieveModelMixin
class TeacherDetailView(RetrieveAPIView): lookup_field = 'pk' # 数据库里的字段 lookup_url_kwarg = 'id' # 过滤字段的条件,从路由传参数过来的 queryset = Teacher.objects.all() serializer_class = TeacherDetailSer
4. UpdateAPIView
- 提供 put 和 patch 方法,可以更新或者局部更新某条数据
继承自:GenericAPIView、UpdateModelMixin
class TeacherUpdateView(UpdateAPIView): lookup_field = 'pk' # 数据库里的字段 lookup_url_kwarg = 'id' # 过滤字段的条件,从路由传参数过来的 queryset = Teacher.objects.all() serializer_class = TeacherUpdateSer
5. DestoryAPIView
- 提供 delete 方法,可以删除某条存在数据
继承自:GenericAPIView、DestoryModelMixin
class TeacherDestoryView(DestroyAPIView): lookup_field = 'pk' # 数据库里的字段 lookup_url_kwarg = 'id' # 过滤字段的条件,从路由传参数过来的 queryset = Teacher.objects.all()
6. ListCreateAPIView
- 提供 post 和 get 方法,可以创建一条数据,或获取列表数据
继承自:GenericAPIView、CreateModelMixin、ListModelMixin
class TeacherListCreateView(ListCreateAPIView): queryset = Teacher.objects.all() serializer_class = TeacherListCreateSer # 共用一个序列化器同时实现创建和数据展示
7. RetrieveUpdateAPIView
- 提供 get、put、patch 方法,可以获取一条数据详情,也可以更新一条数据
继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin
class TeacherRetrieveUpdateView(RetrieveUpdateAPIView): lookup_field = 'pk' # 数据库里的字段 lookup_url_kwarg = 'id' # 过滤字段的条件,从路由传参数过来的 queryset = Teacher.objects.all() serializer_class = TeacherRetrieveUpdateSer
8. RetrieveDestroyAPIView
- 提供 get 和 delete 方法,可以获取和删除一条已存在数据
继承自:GenericAPIView、RetrieveModelMixin、DestoryModelMixin
class TeacherRetrieveDestroyView(RetrieveDestroyAPIView): lookup_field = 'pk' # 数据库里的字段 lookup_url_kwarg = 'id' # 过滤字段的条件,从路由传参数过来的 queryset = Teacher.objects.all() serializer_class = TeacherDeatilSer
9. RetrieveUpdateDestoryAPIView
- 提供 get、put、patch、delete 方法,啥也能干
继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
class TeacherAll(RetrieveUpdateDestroyAPIView): lookup_field = 'pk' # 数据库里的字段 lookup_url_kwarg = 'id' # 过滤字段的条件,从路由传参数过来的 queryset = Teacher.objects.all() serializer_class = TeacherRetrieveUpdateSer
三、通过示例代码逐步展示封装流程
逻辑代码展示:(可通过查看继承类的源码加深理解)
#views.py from rest_framework.generics import GenericAPIView from rest_framework.response import Response from app.models import StudentModel from app.ser_student import StudentSerializer # 混入类 from rest_framework.mixins import ListModelMixin,CreateModelMixin from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin # 扩展类 from rest_framework.generics import ListAPIView,CreateAPIView from rest_framework.generics import RetrieveAPIView,UpdateAPIView,DestroyAPIView from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView # 视图集 from rest_framework.viewsets import ModelViewSet # GenericAPIView # 混入类 # 扩展类 #混入类和扩展类的使用 # 1.测试 GenericAPIView # class IndexGenViews(GenericAPIView): # queryset = StudentModel.objects.all() #查询结果集 # serializer_class = StudentSerializer #序列化器 # # lookup_field = 'pk' #指定数据库中字段 # lookup_url_kwarg = 'id' # # # def get(self, request): # stus = self.get_queryset() # ser = self.get_serializer(instance=stus, many=True) # return Response({"message":"success","data":ser.data}) # ------------------------------------------- # 2.测试 GenericAPIView 配合混入类使用 # class IndexGenViews(GenericAPIView, ListModelMixin,CreateModelMixin): # queryset = StudentModel.objects.all() # serializer_class = StudentSerializer # # def get(self, request): # return self.list(request) # def post(self, request): # return self.create(request) # class IndexGenIDViews(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin): # queryset = StudentModel.objects.all() # serializer_class = StudentSerializer # lookup_field = 'pk' # lookup_url_kwarg = 'id' # # def get(self, request, id): # return self.retrieve(request) # def put(self, request, id): # return self.update(request) # def delete(self, request, id): # return self.destroy(request) # ------------------------------------------------------------ # 3. 测试 扩展类 # class IndexGenViews(ListAPIView,CreateAPIView): # queryset = StudentModel.objects.all() # serializer_class = StudentSerializer # class IndexGenIDViews(RetrieveAPIView,UpdateAPIView,DestroyAPIView): # queryset = StudentModel.objects.all() # serializer_class = StudentSerializer # lookup_field = 'pk' # lookup_url_kwarg = 'id' # 4. 测试 再次封装的扩展类 class IndexGenViews(ListCreateAPIView): queryset = StudentModel.objects.all() serializer_class = StudentSerializer class IndexGenIDViews(RetrieveUpdateDestroyAPIView): queryset = StudentModel.objects.all() serializer_class = StudentSerializer lookup_field = 'pk' lookup_url_kwarg = 'id' # 5. 测试,再次封装,ModelViewSet(视图集详解在下篇文章) class IndexModelSetViews(ModelViewSet): queryset = StudentModel.objects.all() serializer_class = StudentSerializer lookup_field = 'pk' lookup_url_kwarg = 'id'