Django之DRF框架学习(Django REST framework)—— 使用GenericAPIView开发案例

Django之DRF框架学习(Django REST framework)—— 使用GenericAPIView开发案例

  • 一、 Request与Response
    • 1.1 Request
    • 1.2 Response
  • 二、GenericAPIView 与 扩展类Mixin
    • GenericAPIView代码案例
    • Mixins类源码
    • 使用GenericAPIView + Mixin扩展类实现 api的开发
    • 使用ListAPIView + ListCreateAPIView, RetrieveUpdateDestroyAPIView等类实现 api的开发

一、 Request与Response

1.1 Request

REST framework 传入视图的request对象不再是Django默认的requset的对象,而是REST framework提供的扩展了HttpRequest类的Requset类的对象,

REST framework 提供了Parser解析,在接收到请求后会自动根据Content-Type指明的请求数据(例如Json 表单等)将请求数据进行parse解析,解析为类字典对象保存到Request对象中。

  • 常用属性
    • .date
      request.data 返回解析后的请求体数据,类似于Django中标准的request.POST或者 request.FILES 属性提供如下属性
    1. 包含了解析后的文件或者非文件数据
    2. 包含对POST PUT PATCH请求方式解析后的数据
    3. 利用了 REST framework的parsers解析器,不仅支持表单类型的数据,也支持JSON数据
    • query__params
      request.query_params 与 Django标准的requset.GET相同,只是更换了更正确的名称而已

1.2 Response

REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换成符合前端需求的类型。
REST framewo提供了 Renderer渲染器,用来根据请求头中的Accept(接收数据类型声明)来自动转换响应数据到对应格式,如果前端未进行Accept声明,则采用默认方式响应数据,可以通过配置来修改格式.

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES':(  #默认响应渲染类
        'rest_framework.renderers.JSONRenderder', #JSON渲染器
        'rest_framework.renderers.BrowsableAPIRenderer'  #浏览API渲染器
    )
}

二、GenericAPIView 与 扩展类Mixin

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

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

  • 属性
    • serializer_class 指明视图使用的序列化器
  • 方法
    • get_serializer_class(self) 返回序列化器类,默认返回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
      该方法会默认使用APIVie提供的check_object_permissions方法检查当前对象是否有权限被访问

GenericAPIView代码案例

from rest_framework.response import Response

from booktest.models import BookInfo,HeroInfo
from .serializers import BookInfoModelSerializer,HeroInfoModelSerializer
from rest_framework import status

from rest_framework.generics import GenericAPIView

'''使用GenericAPIView实现增删改查'''
class BookListGenericView(GenericAPIView):
    '''列表视图'''
    # 指定序列化器类
    serializer_class = BookInfoModelSerializer
    # 指定查询集'数据来源'
    queryset = BookInfo.objects.all()

    def get(self, request):
        qs = self.get_queryset()
        serializer = self.get_serializer(qs, many=True)
        return Response(serializer.data, status.HTTP_200_OK)

class BookDetailGenericView(GenericAPIView):
    '''详情视图'''
    # 指定序列化器类
    serializer_class = BookInfoModelSerializer
    # 指定查询集'数据来源'
    queryset = BookInfo.objects.all()

    def get(self, request, pk):
        book = self.get_object()
        serializer = self.get_serializer(book)
        return Response(serializer.data)

    def put(self, request, pk):
        book = self.get_object()
        serializer = self.get_serializer(book, request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

Mixins类源码

"""
Basic building blocks for generic class based views.

We don't bind behaviour to http method handlers yet,
which allows mixin classes to be composed in interesting ways.
"""
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()

使用GenericAPIView + Mixin扩展类实现 api的开发

from booktest.models import BookInfo,HeroInfo
from .serializers import BookInfoModelSerializer,HeroInfoModelSerializer
from rest_framework import status

from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin,CreateModelMixin,DestroyModelMixin,UpdateModelMixin,RetrieveModelMixin


'''使用GenericAPIView + Mixin '''
class BookListGenericView(CreateModelMixin, ListModelMixin,GenericAPIView):
    '''列表视图'''
    # 指定序列化器类
    serializer_class = BookInfoModelSerializer
    # 指定查询集'数据来源'
    queryset = BookInfo.objects.all()

    # 获取所有记录
    def get(self, request):
        return self.list(request)

    # 添加新纪录
    def post(self, request):
        return self.create(request)

class BookDetailGenericView(RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin, GenericAPIView):
    '''详情视图'''
    # 指定序列化器类
    serializer_class = BookInfoModelSerializer
    # 指定查询集'数据来源'
    queryset = BookInfo.objects.all()

    # 获取单个记录
    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)

使用ListAPIView + ListCreateAPIView, RetrieveUpdateDestroyAPIView等类实现 api的开发

from booktest.models import BookInfo,HeroInfo
from .serializers import BookInfoModelSerializer,HeroInfoModelSerializer

from rest_framework.generics import GenericAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView

'''ListCreateAPIView, RetrieveUpdateDestroyAPIView等类实现api'''
class BookListGenericView(ListCreateAPIView):
    '''列表视图'''
    # 指定序列化器类
    serializer_class = BookInfoModelSerializer
    # 指定查询集'数据来源'
    queryset = BookInfo.objects.all()

class BookDetailGenericView(RetrieveUpdateDestroyAPIView):
    '''详情视图'''
    # 指定序列化器类
    serializer_class = BookInfoModelSerializer
    # 指定查询集'数据来源'
    queryset = BookInfo.objects.all()

谢谢您的观看~~

Django之DRF框架学习(Django REST framework)—— 使用GenericAPIView开发案例_第1张图片

你可能感兴趣的:(后端,Python,api,django)