drf05

内容概要

  • 反序列化类校验部分源码解析
  • 断言
  • drf之请求
  • drf之响应
  • 视图组件介绍及两个视图基类
  • 基于GenericAPIView+5个视图扩展类

反序列化类型校验部分源码解析

入口跟form组件一样is_valide

image-20230203175703238

image-20230203180257079

image-20230203180458998

image-20230203180708875

先看全局钩子

image-20230203180820360

看局部钩子

image-20230203183048536

断言

源码中大量使用tryassert(断言)

关键字assert,断定你是xx,如果不是就抛出异常

image-20230203190134631

image-20230203190150057

drf之请求

  1. 需求是该接口只能接收jaon格式数据,不能接收其他格式

    总共有三个:from rest_framework

    image-20230203200853556

    api_settings 在drf自己的settings里面

    image-20230203201104846

    导入三种编码格式

    from rest_framework.parsers import JSONParser, FormParser, MultiPartParser

    方式一:在继承自APIView及其子类的视图类中配置(局部配置)

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
    
    
    class BooksView(APIView):
        parser_classes = [JSONParser, ]
    
        def post(self, request):
            print(request.data)
            print(type(request.data))
            return Response()
    
    

    image-20230203202751679

    image-20230203202944567

    image-20230203203032620

    image-20230203203053103

    方法二:在django的setting里面写,这个是全局配置

    image-20230203203519028

    image-20230203203752588

    image-20230203203841374

    image-20230203203902389

    image-20230203203913604

    配置文件的应用顺序,先局部----全局---drf默认的。

    方式三:全局配 1 个,某个视图类像要三个

    在那个视图里面配个局部的 3个即可

drf之响应

  1. Response能够响应的编码格式

    drf 是django的一个 app,所以需要注册

    drf的响应,如果使用浏览器和postman访问同一个接口,返回格式是不用的

    drf做个判断,如果是浏览器,返回的格式好看一些如果是postman只要json数据

    image-20230207152624710

    默认是两种方式,修改方式跟request一样。

    image-20230203205839453

    image-20230203205904344

    image-20230203205915236

    同样发get请求,两种返回的格式不一样

    因为,在浏览器Response返回的是BrowsableAPIRenderer

    image-20230203210056474

    image-20230203210107150

    image-20230203210116283

    方式二 在django的配置文件里写

    image-20230207152851523

    方式三:使用顺序(一般就用内置的即可)
    优先使用视图类中的配置,其次使用项目配置文件中的配置,最后使用内置的

  2. Response的源码属性或方法

    class Response(SimpleTemplateResponse):
        """
        An HttpResponse that allows its data to be rendered into
        arbitrary media types.
        """
    
        def __init__(self, data=None,
                     status=None,
                     template_name=None, 						 headers=None,
                     exception=False, 							 content_type=None):
    

    默认参数

    1. data 是返回的数据列表,字典,字符串

      ser.data(序列化成字典)---序列化后返回给前端

    2. status:http响应的状态码,默认是200,可以自己改

      def get(self, request):
          return Response({"name": 123}, status=300)
      

      image-20230203211003049

      drf在status包下,把所有http响应状态码都写了一遍,常量

      from rest_framework.status import HTTP_200_OK

      image-20230203211138836

      def get(self, request):
          return Response({"name": 123}, status=HTTP_200_OK)
      

      image-20230203211329731

    3. template_name:修改响应模板的样子。

    4. headers:响应头,http响应的响应头

      -原生django怎么在响应头中加东西

      def get(self, request):
          obj = HttpResponse("123")
          obj['xxx'] = 'yyy'
          return obj
      

      image-20230203212434592

      drf的Response在响应头里加东西

      def get(self, request):
          return Response({"name": 123}, status=HTTP_200_OK, headers={"wuhu": 'huhu'})
      

      image-20230203212727747

      跨域请求的时候需要在响应头里面添加

    5. content_type :响应编码格式,一般不动

视图组件介绍及两个视图基类

drf视图,视图类,学过APIView,drf的基类,drf提供的最顶层的类

APIView跟之前的View区别

  • 传入到视图方法中的是rest_fromework的Request对象,而不是Django的HttpResponse对象
  • 视图方法可以返回rest_fromework的Response对象
  • 任何APIException异常都会被不会到,并且处理成合适的响应信息
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检测、流量控制

两个视图基类

APIView

​ -类属性

​ renderer_classes 响应格式

​ parser_classes 能够解析的请求格式

​ authentication_classes 认证类

​ throttle_classes 频率类

permission_classes        权限类

基于APIView + ModelSerializer + Response写5个接口

视图类

from app01 import models

from .serializer import BookSerializer


class BooksView(APIView):
    def get(self, request):
        book = models.Book.objects.all()
        res = BookSerializer(instance=book, many=True)
        return Response(status=HTTP_200_OK, data=res.data)

    def post(self, request):
        res = BookSerializer(data=request.data)
        if res.is_valid():
            res.save()
            return Response(status=HTTP_200_OK, data={'msg': '添加成功'})
        else:
            return Response(status=101, data={'msg': res.errors})


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

    def put(self, request, pk):
        book = models.Book.objects.filter(pk=pk).first()
        res = BookSerializer(instance=book, data=request.data)
        if res.is_valid():
            res.save()
            print(11)
            return Response(status=HTTP_200_OK, data={'msg': '修改成功'})
        else:
            return Response(status=101, data={'msg': res.data})

    def delete(self, reqeust, pk):
        models.Book.objects.filter(pk=pk).delete()
        return Response()

序列化类

from rest_framework import serializers
from .models import Book


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish', 'authors', 'publish_dict', 'authors_list']
        extra_kwargs = {
            'publish': {'write_only': True},
            'authors': {'write_only': True}
        }
        publish_dict = serializers.DictField(read_only=True)
        authors_list = serializers.ListField(read_only=True)

模型层

class Book(models.Model):
    name = models.CharField(max_length=32, verbose_name="书名")
    price = models.CharField(max_length=12, verbose_name="价格")
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')

    @property
    def publish_dict(self):
        return {"name": self.publish.name, "addr": self.publish.addr}

    @property
    def authors_list(self):
        l = [{"name": author_obj.name, "gender": author_obj.gender.get_gender_display()} for author_obj in
             self.authors.all()]
        return l

    class Meta:
        verbose_name_plural = '图书表'

    def __str__(self):
        return "图书对象%s" % self.name


class Publish(models.Model):
    name = models.CharField(max_length=32, verbose_name='出版社名称')
    addr = models.CharField(max_length=12, verbose_name='出版社地址')

    class Meta:
        verbose_name_plural = '出版社表'

    def __str__(self):
        return '出版社对象%s' % self.name


class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name='作者名称')
    gender = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = '作者表'

    def __str__(self):
        return '作者对象%s' % self.name


class AuthorDetail(models.Model):
    choice_dict = ((1, '男'), (2, '女'))
    gender = models.IntegerField(choices=choice_dict, verbose_name='性别')

    class Meta:
        verbose_name_plural = '作者详情表'

路由

path('books/', views.BooksView.as_view()),
path('books/<int:pk>/', views.Books2View.as_view())

基于GenericAPIView + 5个视图扩展类

视图类

from rest_framework.mixins import CreateModelMixin  # 添加
from rest_framework.mixins import UpdateModelMixin  # 修改
from rest_framework.mixins import DestroyModelMixin  # 删除
from rest_framework.mixins import RetrieveModelMixin  # 查询一个
from rest_framework.mixins import ListModelMixin  # 查询所有

from rest_framework.generics import GenericAPIView


class BooksView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = models.Book.objects.all()  # 查所有
    serializer_class = BookSerializer  # 序列化类

    def get(self, request):
        return self.list(request)  # 查所有

    def post(self, request):
        return self.create(request)


class Books2View(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, reqeust, *args, **kwargs):
        return self.update(reqeust, *args, **kwargs)

    def delete(self, reqeust, *args, **kwargs):
        return self.destroy(reqeust, *args, **kwargs)

序列化类

from rest_framework import serializers
from .models import Book


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish', 'authors', 'publish_dict', 'authors_list']
        extra_kwargs = {
            'publish': {'write_only': True},
            'authors': {'write_only': True}
        }
        publish_dict = serializers.DictField(read_only=True)
        authors_list = serializers.ListField(read_only=True)

路由

path('books/', views.BooksView.as_view()),
path('books/<int:pk>/', views.Books2View.as_view())
posted @ 2023-02-03 23:20  可否  阅读(34)  评论(0)    收藏  举报