yuanxiaojiang
人的放纵是本能,自律才是修行

视图继承关系

 

两个视图基类

  APIView

# from rest_framework.views import APIView

APIView是REST framework提供的所有视图的基类,继承自Django的view父类

 APIView与View的不同之处:

  • 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
  • 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。

 APIView支持定义的类属性:

  • authentication_classes 列表或元祖,身份认证类
  • permissoin_classes 列表或元祖,权限检查类
  • throttle_classes 列表或元祖,流量控制类

 基于APIView写的五种接口

class Book(models.Model):
    name=models.CharField(max_length=32)
    price=models.DecimalField(max_digits=5,decimal_places=2)
    publish=models.CharField(max_length=32)
models.py
from rest_framework import serializers
from app01.models import Book
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'
ser.py
from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'^books/(?P<pk>\d)', views.BookAPIView.as_view()),
    path('books/', views.BooksAPIView.as_view())
]
urls.py
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.ser import BookSerializer
from app01.models import Book

class BookAPIView(APIView):
    def get(self,request,pk):
        book = Book.objects.filter(id=pk).first()
        book_ser = BookSerializer(instance=book)
        return Response(book_ser.data)
    def put(self,request,pk):
        book = Book.objects.filter(id=pk).first()
        book_ser = BookSerializer(instance=book,data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response({'status':101,'message':'修改失败'})
    def delete(self,request,pk):
        Book.objects.filter(id=pk).delete()
        return Response({'status':100,'message':'删除成功'})


class BooksAPIView(APIView):
    def get(self,request):
        books = Book.objects.all()
        books_ser = BookSerializer(instance=books,many=True)
        return Response(books_ser.data)
    def post(self,request):
        book_ser = BookSerializer(data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response({'status':101,'message':'添加失败'})
views.py

  GenericAPIView[通用视图类]

# from rest_framework.generics import GenericAPIView

 

继承自APIView,主要增加了操作序列化器和数据库查询的方法,作用是为Mixin扩展类的执行提供方法支持。通常在使用时,可以搭配一个或多个Mixin扩展类。

  GenericAPIView提供的关于序列化器使用的属性和方法

 提供的关于序列化器使用的属性与方法

  • 属性:

    • serializer_class 指明视图使用的序列化器
  • 方法:

    • get_serializer_class(self)

      当出现一个视图类中调用多个序列化器时,那么可以通过条件判断在get_serializer_class方法中通过返回不同的序列化器类名就可以让视图方法执行不同的序列化器对象了。

      返回序列化器类,默认返回serializer_class,可以重写,例如:

      def get_serializer_class(self):
          if self.request.user.is_staff:
              return FullAccountSerializer
          return BasicAccountSerializer
      
    • get_serializer(self, *args, **kwargs)

      返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法。

      注意,该方法在提供序列化器对象的时候,会向序列化器对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。

      • request 当前视图的请求对象
      • view 当前请求的类视图对象
      • format 当前请求期望返回的数据格式

 提供的关于数据库查询的属性与方法

  • 属性:

    • queryset 指明使用的数据查询集
  • 方法:

    • get_queryset(self)

      返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写,例如:

      def get_queryset(self):
          user = self.request.user
          return user.accounts.all()
      
    • get_object(self)

      返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。

      在试图中可以调用该方法获取详情信息的模型类对象。

      若详情访问的模型类对象不存在,会返回404。

      该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。

      举例:

      # url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),
      class BookDetailView(GenericAPIView):
          queryset = BookInfo.objects.all()
          serializer_class = BookInfoSerializer
      
          def get(self, request, pk):
              book = self.get_object() # get_object()方法根据pk参数查找queryset中的数据对象
              serializer = self.get_serializer(book)
              return Response(serializer.data)
      

 其他可以设置的属性

  • pagination_class 指明分页控制类
  • filter_backends 指明过滤控制后端

  基于GenericAPIView写的五种接口

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5,decimal_places=2)
    publish = models.CharField(max_length=32)
models.py
from rest_framework import serializers
from app01.models import Book
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'
ser.py
from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'^books2/(?P<pk>\d)', views.BookGenericAPIView.as_view()),
    path('books2/', views.BooksGenericAPIView.as_view()),
]
urls.py
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from app01.ser import BookSerializer
from app01.models import Book

class BookGenericAPIView(GenericAPIView):
    # queryset  要传入queryset对象,需要查询的模型类
    # serilaizer_class  使用那个序列化器来序列化这堆数据
    # queryset = Book.objects.all()
    queryset = Book.objects
    serializer_class = BookSerializer
    def get(self,request,pk):
        book = self.get_object()
        book_ser = self.get_serializer(book)
        return Response(book_ser.data)
    def put(self,request,pk):
        book = self.get_object()
        book_ser = self.get_serializer(instance=book,data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response({'status':101,'message':'修改失败'})
    def delete(self,request,pk):
        ret = self.get_object().delete()
        return Response({'status':100,'message':'删除成功'})


class BooksGenericAPIView(GenericAPIView):
    queryset = Book.objects
    serializer_class = BookSerializer
    def get(self,request):
        book = self.get_queryset()
        books_ser = self.get_serializer(instance=book,many=True)
        return Response(books_ser.data)
    def post(self,request):
        book_ser = self.get_serializer(data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response({'status':101,'message':'添加失败'})
views.py

  基于GenericAPIView和五个视图扩展类写的接口

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5,decimal_places=2)
    publish = models.CharField(max_length=32)
models.py
from rest_framework import serializers
from app01.models import Book
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'
ser.py
from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    re_path(r'^book3/(?P<pk>\d)', views.BookGenericView.as_view()),
    path('books3/',views.BooksGenericView.as_view()),
]
urls.py
from rest_framework.generics import GenericAPIView
from app01.ser import BookSerializer
from app01.models import Book
from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin

class BookGenericView(GenericAPIView,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin):
    queryset = Book.objects
    serializer_class = BookSerializer
    def get(self,request,pk):
        return self.retrieve(request,pk)
    def put(self,request,pk):
        return self.update(request,pk)
    def delete(self,request,pk):
        return self.destroy(request,pk)

class BooksGenericView(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset = Book.objects
    serializer_class = BookSerializer
    def get(self,request):
        return self.list(request)
    def post(self,request):
        return self.create(request)
views.py

  基于ModelViewSet编写5个接口

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5,decimal_places=2)
    publish = models.CharField(max_length=32)
models.py

 

from rest_framework import serializers
from app01.models import Book
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'
ser.py

 

from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    re_path(r'^books4/(?P<pk>\d)', views.BookModelViewSet.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),
    path('books4/',views.BookModelViewSet.as_view(actions={'get':'list','post':'create'}))
    # 当路径匹配,又是get请求,会执行Book5View的list方法
]
urls.py

 

from rest_framework.viewsets import ModelViewSet
class BookModelViewSet(ModelViewSet):
    queryset = Book.objects
    serializer_class = BookSerializer
views.py

 

  继承VIewSetMixin的视图类

 

 

 

 

 

 

 

源码分析ViewSetMixin

# 重写了as_view
# 核心代码(所以路由中只要配置了对应关系,比如{'get':'list'}),当get请求来,就会执行list方法
for method, action in actions.items():
    #method:get
    # action:list
    handler = getattr(self, action)
    #执行完上一句,handler就变成了list的内存地址
    setattr(self, method, handler)
    #执行完上一句  对象.get=list
    #for循环执行完毕 对象.get:对着list   对象.post:对着create

 

在pycharm中查看类的继承关系

 

作业

1 自己封装一个CommonResponse对象,使用方法如下

        return CoomonResponse('100','成功',boo_ser.data)
       return CoomonResponse('101','验证失败',boo_ser.errors)

2 什么是正向代理,什么是反向代理

3 大家都写:分别用APIView,GenericAPIView,5个视图扩展类,GenericAPIView和5个视图扩展类写的接口和ModelViewSet写5个接口

4 今天讲的所有视图类的继承关系,写出来

 

 

posted on 2023-06-09 09:10  猿小姜  阅读(10)  评论(0)    收藏  举报

levels of contents