首页 > 其他分享 >APIView类

APIView类

时间:2024-04-21 21:45:38浏览次数:18  
标签:return request APIView serializers 序列化 data

【一】APIView类的介绍

【1】介绍

​ Django REST Framework(DRF)中的 APIView 类是一个非常重要的基类,用于定义基于类的视图(Class-based Views)来处理 RESTful API 请求。它提供了强大的功能和灵活的扩展点,使得编写 API 视图变得更加简单和灵活。

【2】主要特点和用法

  1. 处理 HTTP 请求方法: APIView 类允许你在一个类中处理多个 HTTP 请求方法(GET、POST、PUT、DELETE 等)。你只需要在 APIView 类中定义对应的方法,例如 get()post()put()delete() 等。
  2. 序列化和反序列化数据: DRF 中的 APIView 类与序列化器(Serializer)类紧密集成,它可以方便地处理请求数据的反序列化以及响应数据的序列化。你可以在 APIView 中使用序列化器来验证和处理请求数据,以及将模型实例转换为 JSON 格式的响应数据。
  3. 权限和认证: APIView 类提供了内置的权限和认证支持,可以通过设置 permission_classesauthentication_classes 属性来配置权限和认证。这使得你可以轻松地实现对 API 视图的权限控制和用户身份验证。
  4. 分页和过滤: DRF 中的 APIView 类还支持分页和过滤,可以通过设置 pagination_classfilter_backends 属性来启用分页和过滤功能。这使得你可以处理大量数据并向客户端提供分页结果。
  5. 异常处理: APIView 类提供了异常处理功能,可以通过重写 handle_exception() 方法来自定义异常处理逻辑。这使得你可以捕获和处理 API 视图中发生的异常,并返回合适的 HTTP 响应。
  6. URL 路由: APIView 类不直接处理 URL 路由,而是通过 Django 的 URL 路由系统将 URL 映射到对应的 API 视图类。你需要在 URL 配置中将 URL 映射到具体的 APIView 类。

【3】做了哪些事?

  1. 去除了csrf认证
  2. 包装了新的request
  3. 做了三大认证
  4. response做了统一返回,处理全局异常

【二】封装的data

​ 通常,当客户端发不同数据格式的post请求时,对于django而言,不能全部都用request.POST方法拿到数据。当客户端以urlencoded或者form-data的格式发来数据可以通过request.POST方法接收,其数据格式是一个类似于字典的对象。但是对于application/json的数据格式则无法接收到,需要自己从request.body里面手动转换,很麻烦

​ 但是对于APIView类封装好的request对象来说,它对比原来的request有一个data属性,可以直接拿到处理好的数据,无论是以什么数据格式发送。

【1】基于View的五个接口

class BookView(View):
    # 查询所有
    def get(self, request):
        obj_list = models.Book.objects.all()
        if not obj_list:
            return_data = {
                'code': 300,
                'message': '暂无数据,查询失败'
            }
            return JsonResponse(return_data)
        data_list = []
        # 手动遍历 处理数据格式 很麻烦!!!
        for obj in obj_list:
            title = obj.title
            price = obj.price
            publish = obj.publish
            data = {
                'title': title,
                'price': price,
                'publish': publish
            }
            data_list.append(data)
        return_data = {
            'code': 200,
            'message': '查询所有书籍成功',
            'results': data_list
        }
        return JsonResponse(return_data)
	# 添加书籍
    def post(self, request):
        book_info = json.loads(request.body)
        models.Book.objects.create(**book_info)
        return_data = {
            'code': 200,
            'message': '创建图书成功'
        }
        return JsonResponse(return_data)


class BookDetailView(View):
    # 查询一本
    def get(self, request, pk):
        obj = models.Book.objects.filter(pk=pk).first()
        if not obj:
            return_data = {
                'code': 300,
                'message': '查无此书'
            }
            return JsonResponse(return_data)
        return_data = {
            'code': 200,
            'message': '查询图书成功',
            'result': {
                'title': obj.title,
                'price': obj.price,
                'publish': obj.publish,
            }
        }
        return JsonResponse(return_data)

    def delete(self, request, pk):
        # 删除书籍
        res = models.Book.objects.filter(pk=pk).delete()
        if not res[0]:
            return_data = {
                'code': 300,
                'message': '没有找到要删除的图书'
            }
            return JsonResponse(return_data)

        return_data = {
            'code': 200,
            'message': '删除图书成功'
        }
        return JsonResponse(return_data)

    def put(self, request, pk):
        # 修改书籍
        book_info = json.loads(request.body)
        res = models.Book.objects.filter(pk=pk).update(**book_info)
        print(res)
        if not res:
            return_data = {
                'code': 300,
                'message': '没有找到要修改的图书'
            }
            return JsonResponse(return_data)

        return_data = {
            'code': 200,
            'message': '修改图书成功'
        }
        return JsonResponse(return_data)

【2】基于APIView写五个接口

​ 首先要导入APIView这个类,drf框架都很规范,从导模块就可以看出来

from rest_framework.views import APIView

​ 以添加一本书为例子,就不需要自己转通过json转格式了,可以直接从request.data取出我传入的数据,十分方便快捷

​ 但是要注意的是,除了以json数据格式发送的数据,通过request.data拿到的数据是真正意义上的字典,而对于其他数据格式来说,request.data拿到的是一个quearyset对象,他的value值是一个字典,在处理数据的时候要格外注意

​ 还有一点是,APIView给我们提供了一个类,Response,以后返回数据的时候都推荐使用这个。

from rest_framework.response import Response

class BookAPIView(APIView):
    info = request.data
    res = models.Book.objects.create(**info)
    return_data = {
        'code': 200,
        'message': '创建图书成功'
    }
    return Response(return_data)

【三】序列化类

​ 当后端拿到前端传来的数据时,需要将其处理,最后将处理好的数据序列化再返还回去,对于序列化这一个步骤,之前都是通过手动处理,将其手动封装成字典,然后再将这个字典序列化成json格式发给前端,虽然很简单,但是十分的麻烦。

​ drf框架提供了一个序列化类Serializer,它实例化得到的对象可以帮我们快速完成对数据的序列化,

​ 在一个项目中,通常我们时新建一个py文件,在里面导入from rest_framework import serializers,然后再写一个类继承Serializer类,然后在类里面写想要序列化的数据对象的字段,它给我的感觉时非常像django的form组件的写法

## serializer.py

from rest_framework import serializers


class BookSerialize(serializers.Serializer):
    title = serializers.CharField()
    price = serializers.IntegerField()
    publish = serializers.CharField()

​ 然后就是对视图类的编写了,首先在view.py里面导入BookSerialize类,拿到类的第一反应就应该是实例化得到对象,然后需要传入对应的参数,最后就可以通过这个对象的data,直接拿到序列化好的数据。

# 这里以查询所有数据为例
class BookAPIView(APIView):
    def get(self, request):
        obj_list = models.Book.objects.all()
        if not obj_list:
            return_data = {
                'code': 300,
                'message': '暂无数据,查询失败'
            }
            return JsonResponse(return_data)
        # 实例化类得到对象
        # 传入参数
        # instance:指的是需要序列化的对象
        # many:如果需要序列化的对象为多个 就需要指的为True
        ser = BookSerialize(instance=obj_list, many=True)

        return_data = {
            'code': 200,
            'message': '查询所有书籍成功',
            'results': ser.data # data方法拿到序列化好的数据
        }
        return Response(return_data)

【四】序列化类的校验

​ 通常我们都是需要对前端传来的数据进行检验的,比如字段不能过长,也不能过短,字段里面不能有敏感词汇,以及两个字段的不能相同等等

​ drf的这个serialize组件也是给我们提供了一套规则的,他有三重验证,字段本身的验证,局部钩子,全局钩子。他的校验顺序是自身校验--->局部钩子--->全局钩子,只有上一层校验通过了才会走到下一层校验。

​ 首先是字段本身的校验,这里举个简单的例子

# 十分的见名知意
class BookSerialize(serializers.Serializer):
    title = serializers.CharField(max_length=8, min_length=3)
    price = serializers.IntegerField(max_value=200, min_value=30)
    publish = serializers.CharField(max_length=8, min_length=3)

局部钩子,通过定义validate_字段名(self,字段名)方法,当校验不通过的时候需要抛出一个错误消息,这个错误消息drf也提供了,通过from rest_framework.exceptions import ValidationError导入,最后将这个字段return出去就行了

class BookSerialize(serializers.Serializer):
    title = serializers.CharField(max_length=8, min_length=3)
    price = serializers.IntegerField(max_value=200, min_value=30)
    publish = serializers.CharField(max_length=8, min_length=3)
	
    # 这里规定书名不能包含'sb'
    def validate_title(self, title):
        if 'sb' in title:
            # 抛出异常
            raise ValidationError('不可以带脏话')
        # 返回字段
        return title

全局钩子,通过定义validate(self, attrs)方法使用,通常需要用到多个字段做校验的时候会用到全局钩子,用法基本和局部钩子一样,返回的时候需要return attrs

class BookSerialize(serializers.Serializer):
    title = serializers.CharField(max_length=8, min_length=3)
    price = serializers.IntegerField(max_value=200, min_value=30)
    publish = serializers.CharField(max_length=8, min_length=3)

    def validate(self, attrs):
        if attrs.get('title') == attrs.get('publish'):
            raise ValidationError('书名不能与社名相同')
        return attrs

【五】渲染错误消息

​ 上面说到的抛出的异常,如ValidationError('书名不能与社名相同')是可以渲染到相应消息里的,比如我要进行添加一本图书的操作,可是经过校验,我给出的数据并不通过,这时候返回给前端的数据的message就可以通过序列化类实例的对象的errors属性拿到。

​ 这里以添加一本书籍为例

class BookAPIView(APIView):

    def post(self, request):
        info = request.data
        ser = BookSerialize(data=request.data)
        if ser.is_valid():
            return_data = {
                'code': 200,
                'message': '创建图书成功'
            } # 这里并不能正真的保存,还需要做一步处理
            return Response(return_data)
        return_data = {
            'code': 300,
            'message': ser.errors # 这里通过errors属性就可以拿到序列化好的错误消息
        }
        return Response(return_data)

【六】反序列化保存

​ 当我们拿到前端给的数据,并且将这些数据转换成自己的语言能识别的数据并且保存就叫反序列化保存。保存的目的也很明确,拿到前端的数据,经过序列化组件的校验,自然就需要保存到数据库。drf的序列化组件也提供了保存的方法。

​ 需要在自己写的序列化类里面重写create方法,这个方法的validated_data参数是上面通过校验的数据,在方法里面创建一个新的对象到数据库,然后返回新的对象就可以了。

class BookSerialize(serializers.Serializer):
    title = serializers.CharField(max_length=8, min_length=3)
    price = serializers.IntegerField(max_value=200, min_value=30)
    publish = serializers.CharField(max_length=8, min_length=3)
	# 重写create方法
    # validated_data是通过校验的数据
    def create(self, validated_data):
        # 需要导入对应的模型表,插入数据
        obj = models.Book.objects.create(**validated_data)
        # 返回对象
        return obj

​ 然后在视图类中直接通过save保存那个serialize对象即可。

class BookAPIView(APIView):

    def post(self, request):
        info = request.data
        ser = BookSerialize(data=request.data)
        if ser.is_valid():
            # 通过save方法保存
            ser.save()
            return_data = {
                'code': 200,
                'message': '创建图书成功'
            }
            return Response(return_data)
        return_data = {
            'code': 300,
            'message': ser.errors
        }
        return Response(return_data)

【七】反序列化修改

​ 修改和保存差不多,修改需要重写serialize类的update属性,在视图文件里面需要把需要更新的对象前端传来的数据传递给serialize对象。它内部通过判断instance是否有值,来判断是修改还是添加。

class BookSerialize(serializers.Serializer):
    title = serializers.CharField(max_length=8, min_length=3)
    price = serializers.IntegerField(max_value=200, min_value=30)
    publish = serializers.CharField(max_length=8, min_length=3)

    def update(self, instance, validated_data):
        # validated_data是一个字典对象
        # 循环拿到键和值
        # 再通过setattr反射 将值赋给instance对象
        for key, value in validated_data.items():
            setattr(instance, key, value)
"""
			上面的方法等同于下面这个方法
			instance是需要修改的对象
            validated_data 是前端传来的数据
            instance.title = validated_data.get('title')
            instance.price = validated_data.get('price')
            instance.publish = validated_data.get('publish')
"""		
		# save保存
        instance.save()
  	  # 最后把这个对象 也就是instance返回即可
        return instance

​ view.py

class BookDetailAPIView(APIView):

    def put(self, request, pk):
        info = request.data
        obj = models.Book.objects.filter(pk=pk).first()
        # 将前端传来的数据传入
        # 将查找出来的对象传入
        ser = BookSerialize(data=request.data, instance=obj)
        if ser.is_valid():
            # 通过校验后保存
            ser.save()
            return_data = {
                'code': 200,
                'message': '修改图书成功'
            }
            return Response(return_data)

标签:return,request,APIView,serializers,序列化,data
From: https://www.cnblogs.com/Hqqqq/p/18149549

相关文章

  • drf序列化用APIView写编写5个接口并校验数据
    步骤:写一个类,继承Serialier在类中写字段,字段就是要序列化的字段在视图函数中,序列化类,实例化得到对象,传入该传的参数调用序列化类对象的serializer.data方法完成序列化【一】写序列化类serializer.pyfromrest_frameworkimportserializersfromrest_framework.e......
  • 2、APIView执行流程以及request对象源码分析
    一、基于View编写5个接口1、创建模型表models.pyfromdjango.dbimportmodelsclassBook(models.Model):name=models.CharField(max_length=64)price=models.IntegerField()publish=models.CharField(max_length=32)2、视图函数views.pyfrom......
  • 02-APIView和序列化
    常规通过CBV的写法#models.pyfromdjango.dbimportmodelsclassBook(models.Model):name=models.CharField(max_length=32)price=models.IntegerField()publish=models.CharField(max_length=64)classMeta:db_table="book&qu......
  • drf : 通用视图类和(GenericAPIView)5个视图扩展类,九个视图子类,视图集。
    视图RESTframework提供了众多的通用视图基类与扩展类,以简化视图的编写。APIViewrest_framework.views.APIViewAPIView是RESTframework提供的所有视图的基类,继承自Django的View父类。GenericAPIView使用[通用视图类]继承自APIVIew,主要增加了操作序列化器和数据库查询的方......
  • drf : APIView执行流程和新的Request源码。APIView和Request对象分析
    DRF基本使用及执行流程分析1.继承APIView使用2.APIView的执行流程路由:path('Book1',view.Book.as_view())-->第二个参数是函数的内存地址-->APIView的as_view的执行结果-->本质还是用了View类的as_viewn内的viewc包函数,去掉了csrf的认证。-->当请求来......
  • APIview源码分析
    1APIview的as_view -内部还是执行了View的闭包函数view-禁用掉了csrf-一切皆对象,函数也是对象函数地址.name=lqz2原生View类中过的as_view中的闭包函数view -本质执行了self.dispatch(request,*args,**kwargs),执行的是APIView的dispatch3APIView的dispatchdef......
  • drf之APIView分析与Request分析
    一、APIView执行流程分析1.1基于APIView+JsonResponse编写接口#原来基于django原生的View编写接口#drf提供给咱们的一个类,以后使用drf写视图类,都是继承这个类及其子类,APIView本身就是继承了Django原生的ViewclassBookView(APIView):defget(self,request):......
  • APIView源码分析
    1.和CBV源码执行流程相似,请求来了先走路由层:path('books/',views.BookView.as_view()) 2.走APIView的as_view方法,代码如下:@classmethoddefas_view(cls,**initkwargs):view=super().as_view(**initkwargs)#调用父类的as_view,view还是View的as_view......
  • drf之请求,drf 之响应,drf之响应格式,两个视图基类,基于GenericAPIView,5个视图扩展类
    drf之请求1.1之请求Request类#data#query_params#用起来跟之前一样了解: request._request视图类的方法中:self是咱们写的视图类的对象,self.request是新的request,self.request是一个HttpRequest对象,它提供了许多属性和方法来访问和处理请求的信息.1.2......
  • drf请求和响应、GenericAPIView封装、5个视图扩展类
    一、drf之请求1、drf之请求Request类视图类继承APIView后多了-0去除了csrf认证-1新的request-request.data-request.query_params-request.其他跟之前一样-request._request是老的-2三大认证-3全局异常2、控制前端请求的编码格式fromrest_fra......