一、视图之两个视图基类
Generic知识总结:
视图类:
| -APIView:之前用过 |
| -GenericAPIView:GenericAPIView继承了APIView |
GenericAPIView
| -类属性: |
| queryset:要序列化的所有数据 |
| serializer_class:序列化类 |
| lookup_field = 'pk' :查询单条时的key值 |
| -方法: |
| -get_queryset():获取所有要序列化的数据【后期可以重写】 |
| -get_serializer : 返回序列化类 |
| -get_object :获取单个对象 |
总结:以后继承GenericAPIView写接口
| 1 必须配置类属性 |
| queryset |
| serializer_class |
| 2 想获取要序列化的所有数据 |
| get_queryset() |
| 3 想使用序列化类: |
| get_serializer |
| 4 想拿单条 |
| get_object |
5.1 使用APIView+序列化类+Response写接口
| from rest_framework.views import APIView |
| |
| from .serializer import BookSerialzier |
| from rest_framework.response import Response |
| from .models import Book |
| |
| |
| class BookView(APIView): |
| def get(self,request): |
| qs = Book.objects.all() |
| ser = BookSerialzier(qs, many=True) |
| return Response({'code': 100, |
| 'msg': '成功', |
| 'results': ser.data}) |
| def post(self,request): |
| ser = BookSerialzier(data=request.data) |
| if ser.is_valid(): |
| ser.save() |
| return Response({'code': 100, |
| 'msg': '成功'}) |
| else: |
| return Response({'code': 100, |
| 'msg': ser.errors}) |
| |
| class BookSerializer(APIView): |
| def get(self, request, pk): |
| book = Book.objects.all().get(pk=pk) |
| ser = BookSerialzier(book) |
| return Response({'code':100, |
| 'msg': '成功', |
| 'results': ser.data}) |
| def put(self,request, pk): |
| book = Book.objects.all().get(pk=pk) |
| ser = BookSerialzier(data=request.data, instance=book) |
| if ser.is_valid(): |
| ser.save() |
| return Response({'code': 100, |
| 'msg': '更新成功'}) |
| else: |
| return Response({'code': 100,'msg':ser.errors}) |
使用GenericAPIView+序列化类+Response写接口
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 人家写的 |
| from rest_framework.generics import GenericAPIView |
| class BookView(GenericAPIView): |
| queryset = Book.objects.all() |
| serializer_class = BookSerializer |
| |
| def get(self, request): |
| qs = self.get_queryset() |
| ser = self.get_serializer(qs, many=True) |
| return Response({'code': 100, |
| 'msg': '成功', |
| 'results': ser.data}) |
| |
| def post(self,request): |
| ser = self.get_serializer(data=request.data) |
| if ser.is_valid(): |
| ser.save() |
| return Response({'code': 100, |
| 'msg': '成功'}) |
| else: |
| return Response({'code': 100, |
| 'msg': ser.errors}) |
| |
| class BookDetailView(GenericAPIView): |
| queryset = Book.objects() |
| serializer_class = BookSerializer |
| |
| def get(self, request, pk): |
| book = self.get_object() |
| ser = self.get_serializer(book) |
| return Response({'code': 100, |
| 'msg': '成功', |
| 'results': ser.data}) |
5.2 使用GenericAPIView+序列化类+Response写接口
| class BookView(GenericAPIView): |
| queryset = Book.objects.all() |
| serializer_class = BookSerialzier |
| |
| def get(self, request): |
| qs = self.get_queryset() |
| ser = self.get_serializer(qs, many=True) |
| return Response({'code': 100, 'msg': '成功', 'results': ser.data}) |
| |
| def post(self, request): |
| ser = self.get_serializer(data=request.data) |
| if ser.is_valid(): |
| ser.save() |
| return Response({'code': 100, 'msg': '成功'}) |
| else: |
| return Response({'code': 100, 'msg': ser.errors}) |
| |
| |
| class BookDetailView(GenericAPIView): |
| queryset = Book.objects.all() |
| serializer_class = BookSerialzier |
| |
| def get(self, request, pk): |
| book = self.get_object() |
| ser = self.get_serializer(book) |
| return Response({'code': 100, 'msg': '成功', 'results': ser.data}) |
| |
| def put(self, request, pk): |
| book = self.get_object() |
| ser = self.get_serializer(data=request.data, instance=book) |
| if ser.is_valid(): |
| ser.save() |
| return Response({'code': 100, 'msg': '更新成功'}) |
| else: |
| return Response({'code': 100, 'msg': ser.errors}) |
二、5个视图扩展类
继承GenericAPIView+5个视图扩展类+序列化类+Response写接口
5个方法:对应
| -查询所有 :ListModelMixin--->list方法 |
| -新增一条:CreateModelMixin--->create方法 |
| -查询单条:RetrieveModelMixin--->retrieve方法 |
| -修改一条:UpdateModelMixin--->update方法 |
| -删除一条:DestroyModelMixin--->destroy方法 |
写5个类(不叫视图类,视图扩展类,需要配合GenericAPIView一起用),每个类有一个方法,以后想写哪个接口,就继承哪个类即可
自己写的
| |
| from rest_framework.response import Response |
| class ListModelMixin: |
| def list(self, request, *args, **kwargs): |
| qs = self.get_queryset() |
| ser = self.get_serializer(qs, many=True) |
| return Response({'code': 100, 'msg': '成功', 'results': ser.data}) |
| |
| |
| class CreateModelMixin: |
| def create(self, request, *args, **kwargs): |
| ser = self.get_serializer(data=request.data) |
| if ser.is_valid(): |
| ser.save() |
| return Response({'code': 100, 'msg': '成功'}) |
| else: |
| return Response({'code': 100, 'msg': ser.errors}) |
| |
| |
| class RetrieveModelMixin: |
| def retrieve(self, request, *args, **kwargs): |
| book = self.get_object() |
| ser = self.get_serializer(book) |
| return Response({'code': 100, 'msg': '成功', 'results': ser.data}) |
| |
| |
| |
| class DestroyModelMixin: |
| def destroy(self, request, *args, **kwargs): |
| self.get_object().delete() |
| return Response({'code': 100, 'msg': '删除成功'}) |
| |
| |
| class UpdateModelMixin: |
| def update(self, request, *args, **kwargs): |
| book = self.get_object() |
| ser = self.get_serializer(data=request.data, instance=book) |
| if ser.is_valid(): |
| ser.save() |
| return Response({'code': 100, 'msg': '更新成功'}) |
| else: |
| return Response({'code': 100, 'msg': ser.errors}) |
用框架自带的
| from .models import Book |
| from .serializer import BookSerialzier |
| from rest_framework.response import Response |
| from rest_framework.generics import GenericAPIView |
| |
| from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, \ |
| RetrieveModelMixin |
| |
| |
| class BookView(GenericAPIView, ListModelMixin, CreateModelMixin): |
| queryset = Book.objects.all() |
| serializer_class = BookSerialzier |
| |
| def get(self, request): |
| return self.list(request) |
| |
| def post(self, request): |
| return self.create(request) |
| |
| |
| |
| class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin): |
| queryset = Book.objects.all() |
| serializer_class = BookSerialzier |
| |
| def get(self, request, *args, **kwargs): |
| return self.retrieve(request, *args, **kwargs) |
| |
| def put(self, request, *args, **kwargs): |
| return self.update(request, *args, **kwargs) |
| |
| def delete(self, request, *args, **kwargs): |
| return self.destroy(request, *args, **kwargs) |
5 个视图扩展类--->不是视图类---》必须配合GenericAPIView及其子类使用---》不能配合APIView使用
5个视图扩展类,每一个类中只有一个方法,完成5个接口中的其中一个,想写多个接口,就要继承多个
三、基于视图子类写接口:9个视图子类--->视图类
自己写的
| ** |
| class ListAPIView(GenericAPIView, ListModelMixin): |
| def get(self, request): |
| return self.list(request) |
| |
| |
| class CreateAPIView(GenericAPIView, CreateModelMixin): |
| def post(self, request): |
| return self.create(request) |
| |
| |
| class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin): |
| def post(self, request): |
| return self.create(request) |
| |
| def get(self, request): |
| return self.list(request) |
| |
| |
使用框架
| from rest_framework.generics import ListAPIView, CreateAPIView, UpdateAPIView, DestroyAPIView, RetrieveAPIView |
| from rest_framework.generics import ListCreateAPIView |
| from rest_framework.generics import RetrieveUpdateDestroyAPIView |
| from rest_framework.generics import RetrieveUpdateAPIView |
| from rest_framework.generics import RetrieveDestroyAPIView |
| |
| |
| |
| class BookView(ListCreateAPIView): |
| queryset = Book.objects.all() |
| serializer_class = BookSerialzier |
| |
| |
| class BookDetailView(RetrieveUpdateDestroyAPIView): |
| queryset = Book.objects.all() |
| serializer_class = BookSerialzier |
四、终极封装:视图集
ModelViewSet:
-继承它后,只需要在视图类中写两行
| class BookView(ModelViewSet): |
| queryset = Book.objects.all() |
| serializer_class = BookSerialzier |
继续扩展
| def list(self, request, *args, **kwargs): |
| res = super().list(request, *args, **kwargs) |
| |
| return Response({'code': 100, 'msg': '成功', 'data': res.data}) |
| |
| def create(self, request, *args, **kwargs): |
| res = super().create(request, *args, **kwargs) |
| print('发送邮件。。。') |
| return Response({'code': 100, 'msg': '新增成功'}) |
| |
| def perform_create(self, serializer): |
| |
| print('发送邮件。。。。') |
| super(BookView, self).perform_create(serializer) |
-配置路由,5个接口都有了
| path('books/', BookView.as_view({'get': 'list', 'post': 'create'})), |
| path('books/<int:pk>/', BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})), |
ModelViewSet 源码分析
| -继承了: |
| mixins.CreateModelMixin, |
| mixins.RetrieveModelMixin, |
| mixins.UpdateModelMixin, |
| mixins.DestroyModelMixin, |
| mixins.ListModelMixin |
| GenericViewSet |
| -ViewSetMixin :没有见过,重写了 as_view |
| -GenericAPIView |
-只要继承了ModelViewSet,路由写法变了,谁控制它变的:ViewSetMixi
ViewSetMixin 如何控制路由写法变了?
| -BookView.as_view 是在执行,其实是ViewSetMixin的as_view |
| @classonlymethod |
| def as_view(cls, actions=None, **initkwargs): |
| |
| def view(request, *args, **kwargs): |
| self = cls(**initkwargs) |
| for method, action in actions.items(): |
| |
| |
| |
| handler = getattr(self, action) |
| |
| setattr(self, method, handler) |
| |
| return self.dispatch(request, *args, **kwargs) |
| return csrf_exempt(view) |
总结:
| ''' |
| 1 只要继承了ViewSetMixin及其子类,路由写法就变了,必须传actions参数 |
| 2 变成映射关系了: |
| path('books/', BookView.as_view({'get': 'list', 'post': 'create'})), |
| 3 以后,只要是books路由匹配成功,的get请求,就会执行视图类BookView的list方法 |
| |
| 4 以后视图类中的方法名,可以随意命名 |
| 5 这个类,必须配合视图类使用(APIView,GenericAPIView,9个视图子类),必须放在视图类之前 |
| ''' |
大总结
-
2个视图基类
-APIView
-GenericAPIView
-
5个视图扩展类(不是视图类,需要配合GenericAPIView及其子类使用)
-
9个视图子类
-
视图集:
ModelViewSet:5个接口的
ReadOnlyModelViewSet:两个接口,list和retrieve
ViewSetMixin:魔法,不能单独使用,必须配合视图类用,路由写法变了
ViewSet:ViewSetMixin+APIView,以后想继承APIView,但是想路由写法变化,视图类中方法可以任意命名
GenericViewSet:ViewSetMixin+GenericAPIView,以后想继承GenericAPIView,但是想路由写法变化,视图类中方法可以任意命名
ReadOnlyModelViewSet,ViewSet,GenericViewSet
| from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet,ViewSetMixin,ViewSet,GenericViewSet |
| from rest_framework.views import APIView |
| |
| |
| |
| class SmsView(ViewSet): |
| def lqz(self, request): |
| return Response('你好') |
五、drf之路由
路由写法有多种
| -原始写法 |
| -映射的写法:path('books/', BookView.as_view({'get': 'list', 'post': 'create'})) |
| -自动生成路由 |
自动生成路由
| -必须要继承ViewSetMixin及其子类的视图类,才能用 |
| -继承了 5个视图扩展类+ViewSetMixin的视图类,能自动生成路由 |
| -跟咱们写的这个是一样的 |
| -path('books/', BookView.as_view({'get': 'list', 'post': 'create'})), |
| -path('books/<int:pk>/', BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})), |
| |
| |
| -自己写的视图类的方法,如何映射 |
| -映射的方式我们会 |
| -自动生成的方式 |
自动生成路由
| 1 继承了 5个视图扩展类+ViewSetMixin的视图类,能自动生成路由(get:list,get:retrieve..) |
| 2 我们自己命名的: 方法名:login send_sms,需要使用装饰器来做 |
| |
| class SMSView(ViewSet): |
| @action(methods=['GET'], detail=False, url_path='lqz', url_name='lqz') |
| def lqz(self, request): |
| |
| router.register('lqz',SMSView,'lqz') |
| |
| 3 action装饰器的参数 |
| methods:请求方式 |
| detail:一个True,一个False,用True,表示生成详情的路径 <int:pk> |
| |
| |
| url_path:路径名字,需要加上前面的路径一起,如果不加,默认以函数名作为路径名 |
| url_name:反向解析使用的名字(用的不多) |
路由类,有两个,用法完全一致,区别是DefaultRouter生成的路径多
| SimpleRouter :用的最多 |
| DefaultRouter |
| |
视图层代码
| |
| from rest_framework.viewsets import ModelViewSet, ViewSet, ViewSetMixin |
| from rest_framework.views import APIView |
| |
| |
| from rest_framework.decorators import action |
| |
| |
| class BookView(ModelViewSet): |
| queryset = Book.objects.all() |
| serializer_class = BookSerialzier |
| |
| @action(methods=['GET'], detail=False) |
| def login(self,request): |
| |
| return Response('登录成功') |
| |
| |
| |
| |
| class SMSView(ViewSet): |
| @action(methods=['GET'], detail=True, url_name='lqz') |
| def lqz(self, request): |
| return Response('你好') |
路由层代码
| from django.contrib import admin |
| from django.urls import path, include |
| |
| |
| |
| from app01.views import BookView, SMSView |
| |
| from rest_framework.routers import SimpleRouter,DefaultRouter |
| |
| |
| router = DefaultRouter() |
| |
| router.register('books', BookView, 'books') |
| |
| |
| router.register('lqz',SMSView,'lqz') |
| |
| |
| |
| |
| |
| path('api/v1/', include(router.urls)), |
| |
| urlpatterns = [ |
| path('admin/', admin.site.urls), |
| |
| path('api/v1/', include(router.urls)), |
| |
| |
| ] |
思维导图and笼统记忆
APIView:
这是DRF中最基础的视图类,提供了处理HTTP请求的基本功能。开发者需要继承该类,并在子类中实现相应的HTTP方法(如get()、post()、put()等)来处理请求。
GenericAPIView:
这是一个更高级的通用视图类,结合了APIView和mixins模块的功能。GenericAPIView提供了一些通用的方法和属性,例如get_object()、get_queryset()等,用于简化开发过程。
ViewSet:
这是DRF中更高级的视图类,结合了GenericAPIView和mixins模块的功能,并提供了更多的功能和灵活性。ViewSet可以处理常见的CRUD操作,包括list()、create()、retrieve()、update()和destroy()等,通过路由器进行注册和映射。
ModelViewSet:
这是一个特殊的ViewSet,专门用于处理与数据库模型相关的操作。ModelViewSet结合了GenericAPIView和ModelMixin的功能,提供了一套完整的CRUD操作,包括列表、创建、检索、更新和删除等。

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步