03视图基类,视图集,视图扩展类....

1:两个视图基类

1.1:APIView视图类

Django REST framwork 提供的视图的主要作用:

  • 控制序列化器的执行(检验、保存、转换数据)
  • 控制数据库查询的执行

1.1.1:APIView:继承了原生Django的View

image-20201122165955651

1.1.2:示例

1.1.2.1:models.py
from django.db import models


# Create your models here.
class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32, null=True)
    price = models.DecimalField(max_digits=5, decimal_places=2, null=True)
    publish = models.CharField(max_length=32, null=True)

1.1.2.2:urls.py
from django.urls import path
from learn import views

urlpatterns = [

    path('books/', views.Book.as_view()),
    path('book/<int:pk>/', views.BookDetail.as_view()),

]

1.1.2.3:views.py
from rest_framework.views import APIView
from . import models
from . import serializer
from . util import APIResponse

# Create your views here.

class Book(APIView):
    def get(self, request, *args, **kwargs):
        book_list = models.Book.objects.all()
        ser = serializer.BookModelSerializer(instance=book_list, many=True)
        return APIResponse(ser.data)

    def post(self,request,*args,**kwargs):
        ser =serializer.BookModelSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return APIResponse(ser.data)
        else:
            return APIResponse(ser.errors,code=100)

class BookDetail(APIView):
    def get(self, request,pk, *args, **kwargs):
        book_obj = models.Book.objects.get(pk=pk)
        ser = serializer.BookModelSerializer(instance=book_obj)
        return APIResponse(ser.data)

    def put(self,request,pk,*args,**kwargs):
        book_obj = models.Book.objects.get(pk=pk)
        ser =serializer.BookModelSerializer(instance=book_obj,data=request.data)
        if ser.is_valid():
            ser.save()
            return APIResponse(ser.data)
        else:
            return APIResponse(ser.errors,code=100)
    def delete(self,request,pk,*args,**kwargs):
        models.Book.objects.filter(pk=pk).delete()
        return APIResponse(msg='删除成功')

1.1.2.3:utils.py
from rest_framework.response import Response


class APIResponse(Response):

    def __init__(self, data=None, msg='successful', code=200, status=None
                 ):
        dic = {'data': data, 'msg': msg, 'code': code}
        super(APIResponse, self).__init__(data=dic, status=status, template_name=None, headers=None,exception=False, content_type=None)

1.1.2.4:serializer

from rest_framework import serializers
from . import models



class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'
        extra_kwargs = {
            "id": {'required': False},
            "title": {'required': True},
            "price": {'required': True},
            "publish": {'required': True},
        }

1.2:GenericAPIView视图类

1.2.1:GenericAPIView:继承了APIView
  1. queryset = models.Book.objects.all()
  2. serializer_class = serializer.BookModelSerializer
  3. get_queryset:获取配置的queryset
  4. get_object:路由中的分组字段必须是pk
  5. get_serializer:获取配置的序列化类

image-20201122170303287

1.2.2:示例

**views.py 其他和示例1.1.2示例差不多

class BookGenericAPIView(GenericAPIView):

    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer

    def get(self, request, *args, **kwargs):
        obj = self.get_queryset()
        ser = self.get_serializer(obj, many=True)
        return APIResponse(ser.data)
    def post(self, request, *args, **kwargs):
        ser=self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
        return APIResponse(ser.data,msg='successful')


class BookDetailGenericAPIView(GenericAPIView):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer

    def get(self, request, *args, **kwargs):
        obj = self.get_object()
        ser = self.get_serializer(obj)
        return APIResponse(ser.data)

    def put(self, request, *args, **kwargs):
        obj = self.get_object()
        ser = self.get_serializer(obj, data=request.data)
        if ser.is_valid():
            ser.save()
        return APIResponse('修改成功')

    def delete(self, request, *args, **kwargs):
        self.queryset.filter(id=kwargs.get('pk')).delete()
        return APIResponse('删除成功')

1.3:总结

  1. APIView:如果跟models没有关系(没有数据库相关操作),就继承它

  2. GenericAPIView:有关数据库操作,queryset 和serializer_class

2: 五个视图扩展类

2.1:自定义视图扩展类

class ListView():
    def list(self,request, *args, **kwargs):
        obj = self.get_queryset()
        ser = self.get_serializer(obj, many=True)
        return Response(ser.data)

class CreateView():
    def create(self,request, *args, **kwargs):
        ser=self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
        return Response('成功')
2.2-1:示例
class BookGenericView(GenericAPIView,CreateView,ListView):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)
2.2-2示例

class BookDetailGenericAPIView(GenericAPIView):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer

    def get(self, request, *args, **kwargs):
        obj = self.get_object()
        ser = self.get_serializer(obj)
        return Response(ser.data)

    def put(self, request, *args, **kwargs):
        obj = self.get_object()
        ser = self.get_serializer(obj, data=request.data)
        if ser.is_valid():
            ser.save()
        return Response('修改成功')

    def delete(self, request, *args, **kwargs):
        self.queryset.filter(id=kwargs.get('pk')).delete()
        return Response('删除成功')

2.2:扩展视图类(rest_framework.mixins)

2.2.1:五个
CreateModelMixin:create方法创建一条
DestroyModelMixin:destory方法删除一条
ListModelMixin:list方法获取所有
RetrieveModelMixin:retrieve获取一条
UpdateModelMixin:update修改一条
2.2.2:扩展视图类源码
from rest_framework import status
from rest_framework.response import Response
from rest_framework.settings import api_settings


class CreateModelMixin:
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}


class ListModelMixin:
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class RetrieveModelMixin:
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)


class UpdateModelMixin:
    """
    Update a model instance.
    """
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)


class DestroyModelMixin:
    """
    Destroy a model instance.
    """
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()

2.2.3示例
from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin, RetrieveModelMixin, \
    UpdateModelMixin
class BookGenericView(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class BookDetailGenericAPIView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer

    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)

3:子类视图

3.1九个子类视图(rest_framework.generics)

CreateAPIView:继承CreateModelMixin,GenericAPIView,有post方法,新增数据
DestroyAPIView:继承DestroyModelMixin,GenericAPIView,有delete方法,删除数据
ListAPIView:继承ListModelMixin,GenericAPIView,有get方法获取所有
UpdateAPIView:继承UpdateModelMixin,GenericAPIView,有put和patch方法,修改数据
RetrieveAPIView:继承RetrieveModelMixin,GenericAPIView,有get方法,获取一条


ListCreateAPIView:继承ListModelMixin,CreateModelMixin,GenericAPIView,有get获取所有,post方法新增
RetrieveDestroyAPIView:继承RetrieveModelMixin,DestroyModelMixin,GenericAPIView,有get方法获取一条,delete方法删除
RetrieveUpdateAPIView:继承RetrieveModelMixin,UpdateModelMixin,GenericAPIView,有get获取一条,put,patch修改
RetrieveUpdateDestroyAPIView:继承RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView,有get获取一条,put,patch修改,delete删除

3.2示例

class CreateListGenericAPIView(GenericAPIView,CreateModelMixin,ListModelMixin):
    def get(self,request,*args,**kwargs):
        return self.list(request,*args,**kwargs)
    def post(self,request,*args,**kwargs):
        return  self.create(request,*args,**kwargs)
from rest_framework.generics import CreateAPIView,ListAPIView,ListCreateAPIView
from rest_framework.generics import UpdateAPIView,RetrieveAPIView,DestroyAPIView,RetrieveUpdateAPIView,RetrieveDestroyAPIView,RetrieveUpdateDestroyAPIView

# class BookGenericView(CreateAPIView):
# class BookGenericView(ListAPIView):
class BookGenericView(ListCreateAPIView):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer


# class BookDetailGenericAPIView(RetrieveAPIView):
# class BookDetailGenericAPIView(RetrieveAPIView,UpdateAPIView):
class BookDetailGenericAPIView(RetrieveUpdateDestroyAPIView):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer

4 视图集

4.1:ViewSetMixin
ViewSetMixin:重写了as_view 

ViewSet:     继承ViewSetMixin和APIView

GenericViewSet:继承ViewSetMixin, generics.GenericAPIView

ModelViewSet:继承mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet

ReadOnlyModelViewSet:继承mixins.RetrieveModelMixin,mixins.ListModelMixin,GenericViewSet
4.2:示例一

urls.py

from django.contrib import admin
from django.urls import path
from learn import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookSetView.as_view(actions={'get':'list','post':"create"})),
    path('book/<int:pk>/', views.BookSetView.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),

]

views.py

from rest_framework.viewsets import ModelViewSet


class BookSetView(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer

4.3:示例二

urls.py

from django.contrib import admin
from django.urls import path
from learn import views

urlpatterns = [
   path('book11/', views.BookView.as_view({'get':'lqz'})),
   path('book22/', views.BookView.as_view({'get':'egon'})),
]

views.py

# ViewSetMixin:视图类中的方法名,可以随便写,只需要映射对就可以
from rest_framework.viewsets import ViewSetMixin,ViewSet
from rest_framework.response import Response

class BookView(ViewSetMixin,APIView):
# class BookView(ViewSet):
    def lqz(self,request,*args,**kwargs):
        print(self.action)

        return Response('lqz')
    def egon(self,request,*args,**kwargs):
        return Response('egon')

5 action的使用

# 只要继承了ViewSetMixin类
# 路由配置:path('books_mix/', views.BookView.as_view({'get':'lqz'}))
# 视图类的方法中就会有个action
class BookView(ViewSet):
    def lqz(self,request,*args,**kwargs):
        print(self.action)
        return Response('lqz')
    
    
# ViewSetMixin以后只要继承它,路由的配置就发生变化了,只需要写映射即可

7 路由的使用

7.1:自动生成路由

# 自动生成路由
# SimpleRouter
# DefaultRouter

# 继承了ViewSetMixin的视图类,以后写路由,可以自动生成
from rest_framework import routers
# 实例化得到一个对象
router = routers.SimpleRouter()
# 注册进路由
router.register('books', views.BookSetView)
# 把自动生成的路由配置到urlpatterns中
	-urlpatterns += router.urls
    -re_path(r'v1/', include(router.urls))

7.2:原生路由配置

# 配置路由的方式
	-最原始的
    	-path('books/', views.BookAPIView.as_view()),
    -ViewSetMixin的视图类
    	-path('books_set/', views.BookSetView.as_view({'get':'list','post':'create'}))
    -ViewSetMixin的视图类
    	-自动生成,7.1

7.3:action路由自动配置

#action
	-当自动生成路由的时候,由于视图类中还有其它方法,是无法自动生成路由的
    -加action装饰器:
    	-methods:什么请求方式会触发被装饰函数的执行
        -detail:是True是基于带id的路由生成的,如果是False,是基于不带id的路由生成的
    	-@action(methods=['get'], detail=True)
7.3.1示例

urls.py

from learn import views
from rest_framework.routers import SimpleRouter
route = SimpleRouter()
route.register('books',views.BookView,basename='books')


urlpatterns = [
]
urlpatterns += route.urls

views.py

from rest_framework.viewsets import ViewSetMixin, ViewSet
from rest_framework.response import Response
from rest_framework.decorators import action


class BookView(ViewSetMixin, APIView):

    @action(methods=['get'],detail=False)
    def lqz(self, request, *args, **kwargs):
        print(self.action, 11111)
        return Response({'name':'lqz'})

    @action(methods=['get'],detail=False)
    def egon(self, request, *args, **kwargs):
        print(self.action)
        return Response({'name':'egon'})

posted @ 2020-12-29 16:18  为了等  阅读(115)  评论(0编辑  收藏  举报