【Django-rest-framework框架】第04回 请求与响应,视图组件

1. Djiago-rest-framework体系

1. 前后端开发模式
2. API接口
3. postman使用
4. 序列化和反序列化
5. restful规范
6. cbv的执行流程
7. APIView 继承了View,执行流程
8. 序列化类
9. 请求与响应
10. 视图层(2基类,5个扩展类,9个子类,视图集)
11. 路由的使用
12. 认证,频率,权限
13. 过滤,排序,分页
14. 全局异常处理
15. 接口文档:自定生成,自己写
16. 前后端分离:jwt认证方式--登录
17. 公司内部:RBAC
18. djagno:admin 美化

2. drf之请求与响应

2.1 Request

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

Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果

2.1.1 常用属性 .data

request.data 返回解析之后的请求体数据。类似于Django中标准的request.POST 和 request.FILES属性,一下特性:

1. 包含了解析之后的文件和非文件数据
2. 包含了对POST, PUT, PATCH请求方式解析后的数据
3. 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据

2.1.2 常用属性 .query_params

request.query_params 与Django标准的 request.GET相同,只是更换了更正确的名称而已

2.2 Response

REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

2.2.1 构造方式

Response(data, status=None, template_name=None, headers=None, content_type=None)

data数据不要是render处理之后的数据,只需传递python的内建类型数据即可,REST framework会使用renderer渲染器处理data

data不能是复杂结构的数据,如Django的模型类对象,对于这样的数据我们可以使用Serializer学列化器序列化处理后(转为了python字典类型)再传递给data参数

2.2.2 参数

1. data:为响应准备的序列化处理后的数据
2. status:状态码,默认为200
3. template_name:模板名称,如果使用HTMLRenderer时需指明
4. headers:用于存放响应头信息的字典
5. content_type:响应数据的Content-Type,通常此参数无需传递,RESR framework会根据前端所需类型数据来设置该参数

2.2.3 模拟

2.2.4 向响应头写数据

Response修改状态码,向响应头写数据

class TestView(APIView):
    def get(self, request):
        a = {'name': 'zhy', 'age': 18}
        # return HttpResponse(json.dumps(a))
        # return JsonResponse(a)
        return Response(a, status=status.HTTP_400_BAD_REQUEST, headers={'name':'zhy'})

原生django向响应头里放数据

class TestView(APIView):
    def get(self, request):
        a = {'name': 'zhy', 'age': 18}
        # 原生django向响应头里放数据如何做
        res = HttpResponse(json.dumps(a))
        # res = JsonResponse(a)
        res['xxx'] = 'yyy'
        return res

3. drf能够解析的请求编码,响应编码

3.1 简介

1. 默认能解析:
   urlencoded
   from-data
   json

2. 其实通过配置完成:项目中没有配置,是在drf内置的配置文件中提前配好了
   drf也是有两套,一套是项目中得配置(settings.py),一套是默认的配置
   drf的配置文件settings.py中有 DEFAULT_PARSER_CLASSES(默认的解析类)
   'rest_framework.parsers.JSONParser', 可以解析json格 
   'rest_framework.parsers.FormParser', 可以解析urlencoded格式
   'rest_framework.parsers.MultiPartParser' 可以解析form-data格式

3.2 实现让我们接口只能接受json格式

3.2.1 方式1:全局配置,项目配置文件

3.2.2 方式2: 局部配置

3.2.3 总结

1. 解析类的使用顺序:优先用视图类自己的,然后用项目配置文件,最后用内置的
2. 实际项目如何配置
   基本上都运行JSONParser,FormParser
   如果上传文件只允许MultiPartParser
3. 实际编码中,响应一般不配,就用默认

4. drf之视图组件

Django REST framwork 提供的视图的主要作用:
    控制序列化器的执行(检验、保存、转换数据)
    控制数据库查询的执行

REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。
由于drf提供了一个顶层的视图类APIView,咱们可以通过继承APIView写视图类
后期咱们要写的代码可能重复代码比较多,就可以使用面向对象的继承,封装



GenericAPIView-->继承了APIView
类属性:
     queryset = User.objects.all()
     serializer_class = UserSerializer
方法:
     self.get_object() # 根据pk获取单个数据
     self.get_serializer # 获取要使用的序列化类
     self.get_queryset() # 获取所有要序列化数据

5. 基于APIView的5个接口

serializer

from rest_framework import serializers

from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

views

from rest_framework.response import Response
from rest_framework.views import APIView
from .serializer import BookSerializer
from .models import Book


class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        ser = BookSerializer(instance=book_list, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '新增成功'}, status=201)
        else:
            return Response({'code': 101, 'msg': ser.errors})


class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        res = BookSerializer(instance=book)
        return Response(res.data)

    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book,data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code':100,'msg':'修改成功'},status=201)
        else:
            return Response({'code':101,'msg':ser.errors})

    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response('')

urls

urlpatterns = [
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>', views.BookDetailView.as_view()),
]

6. 基于GenericAPIView的个接口

serializer

from rest_framework import serializers

from .models import User

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

views


from rest_framework.generics import GenericAPIView


class UserView(GenericAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get(self, request):
        user_list = self.get_queryset()
        ser = self.get_serializer(instance=user_list, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '新增成功'}, status=201)
        else:
            return Response({'code': 101, 'msg': ser.errors})


class UserDetailView(GenericAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get(self, request, pk):
        user = self.get_object()
        res = self.get_serializer(instance=user)
        return Response(res.data)

    def put(self, request, pk):
        user = self.get_object()
        ser = self.get_serializer(instance=user, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功'}, status=201)
        else:
            return Response({'code': 101, 'msg': ser.errors})

    def delete(self, request, pk):
        self.get_queryset().filter(pk=pk).delete()
        return Response('')

urls

urlpatterns = [
    path('user/', views.UserView.as_view()),
    path('user/<int:pk>', views.UserDetailView.as_view()),
]

7. 作业

1. 使用GenericAPIView写出book的5个接口

views

from django.shortcuts import render

# Create your views here.
from .models import Book
from rest_framework.response import Response
from .serializer import BookSerializer
from rest_framework.generics import GenericAPIView


class BookView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):
        book_list = self.get_queryset()
        res = self.get_serializer(instance=book_list, many=True)
        return Response(res.data)

    def post(self, request):
        res = self.get_serializer(data=request.data)
        if res.is_valid():
            res.save()
            return Response({'code': 100, 'msg': '新增成功'}, status=201)
        else:
            return Response({'code': 101, 'msg': res.errors})


class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

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

    def put(self, request, pk):
        book = self.get_object()
        res = self.get_serializer(instance=book, data=request.data)
        if res.is_valid():
            res.save()
            return Response({'code': 100, 'msg': '修改成功'}, status=201)
        else:
            return Response({'code': 101, 'msg': res.errors})

    def delete(self,request,pk):
        self.get_queryset().filter(pk=pk).delete()
        return Response('')

serializer

from rest_framework import serializers

from .models import Book


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

2. 使用面向对象,写5个父类, 继承GenericAPIView+某几个父类后,就有某几个接口



class AllBook(GenericAPIView):
    def get(self, request):
        book_list = self.get_queryset()
        res = self.serializer_class(instance=book_list, many=True)
        return Response(res.data)


class PostBook(GenericAPIView):
    def post(self, request):
        res = self.serializer_class(data=request.data)
        if res.is_valid():
            res.save()
            return Response({'code': 100, 'msg': '新增成功'}, status=201)
        else:
            return Response({'code': 100, 'msg': res.errors})


class OneBook(GenericAPIView):
    def get(self, request, pk):
        book = self.get_object()
        res = self.serializer_class(instance=book)
        return Response(res.data)


class PutBook(GenericAPIView):
    def put(self, request, pk):
        book = self.get_object()
        res = self.serializer_class(instance=book, data=request.data)
        if res.is_valid():
            res.save()
            return Response({'code': 100, 'msg': '修改成功'})
        else:
            return Response({'code': 101, 'msg': res.errors})


class DeleteBook(GenericAPIView):
    def delete(self, request, pk):
        self.get_queryset().filter(pk=pk).delete()
        return Response('')


class BookView(AllBook, PostBook):
    queryset = Book.objects.all()
    serializer_class = BookSerializer


class BookDetailView(OneBook, PutBook, DeleteBook):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

3. 9个视图子类

class AllBook(GenericAPIView):
    pass
class PostBook(GenericAPIView):
    pass
class OneBook(GenericAPIView):
    pass
class PutBook(GenericAPIView):
    pass
class DeleteBook(GenericAPIView):
    pass
class AllBookAndPostBook(AllBook,PostBook):
    pass
class OneBookAndPutBook(OneBook,PutBook):
    pass
class PutBookAndDeleteBook(PutBook,DeleteBook):
    pass
class OneBookAndDeleteBook(OneBook,DeleteBook):
    pass
class OneBookAndPutBookAndDeleteBook(OneBook,PutBook,DeleteBook)
    pass

class BookView(AllBookAndPostBook):
    queryset = Book.objects.all()
    serializer_class = BookSerializer


class BookDetailView(OneBookAndPutBookAndDeleteBook):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
posted @ 2022-09-29 19:56  |相得益张|  阅读(75)  评论(1编辑  收藏  举报