首页 > 其他分享 >APIView的基本使用与序列化组件

APIView的基本使用与序列化组件

时间:2022-09-26 23:24:15浏览次数:64  
标签:return name APIView self request book 组件 序列化 data

APIView的基本使用

1.drf是一个第三方app,只能在django中使用

2.安装drf后,导入视图类APOIView,所有后期要使用drf写视图类,都是继承AOIView及其子类

3.在app注册中注册rest_framework
'rest_framework'

View+JsonResponse

from .models import Book
from django.views import View
from django.http import JsonResponse

class BookView(View):
    def get(self, request):
        # 获取表中所有数据
        book_list = Book.objects.all()
        # book_list是queryset对象不能直接序列化,只能通过for循环成列表套字典的形式
        res = []
        for book in book_list:
            res.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        # 如果safe不是False且不是字典,则抛异常,显示中文
        return JsonResponse(res, safe=False, json_dumps_params={'ensure_ascii': False})

APIView+drf的Response写

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


class BookView(APIView):
    def get(self, request):
        # 获取表中所有数据
        book_list = Book.objects.all()
        # book_list是queryset对象不能直接序列化,只能通过for循环成列表套字典的形式
        res = []
        for book in book_list:
            res.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        # 如果safe不是False且不是字典,则抛异常,显示中文
        return Response(res)

APIView源码分析

1.视图类继承APIView后,执行流程就发生了变化,这个变化就是drf的执行流程

2.找视图类as_view,先去APIView
@classmethod
def as_view(cls, **initkwargs):
    # 调用了父类(View)的as_view
    view = super().as_view(**initkwargs)
	# 之后所有的请求都没有csrf的校验
    return csrf_exempt(view)
	'''
	我们之前使用的装饰器去掉csrf校验
	@csrf_exempt
    def index(request):
    	pass
    本质上就是:index = csrf_exempt(index)
	'''

3.当请求来了是,路由匹配成功会执行View类的as_view类方法内的view闭包函数,但是没有csrf认证,真正执行了self.dispatch(APIView的dispatch)
    def dispatch(self, request, *args, **kwargs):
        # 参数的request是原来django原生的request
        # 后面的request变成了drf提供的request类的对象
        request = self.initialize_request(request, *args, **kwargs)
        # self是视图对象,视图对象.request = 新的request
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
        try:
            # 执行了认证、频率、权限
            self.initial(request, *args, **kwargs)
            # 请求方式转成小写,判断是否在http_method_names中
            if request.method.lower() in self.http_method_names:
                # 去self对象找request.method.lower(),找打则返回这个方法,没找到则返回
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            response = handler(request, *args, **kwargs)
        except Exception as exc:
            # 捕捉异常,处理后正常返回
            # 在执行三大认证和视图类的方法过程中,如果出了异常,都会被捕获处理>>>全局异常的处理
            response = self.handle_exception(exc)
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
'''
1.只要继承APIView都没有csrf的认证
2.后面的request都变成了drf提供的request类的对象
3.执行视图函数之前,执行了三大认证(认证、权限、频率)
4.在执行三大认证和视图类的方法过程中,如果出了异常,都会被捕获处理
'''

Request类源码分析

1.视图中使用的request对象,已经变成drf提供的Request类的对象
1.1原生django的request是这个类的对象
django.core.handlers.wsgi.WSGIRequest
1.1drf的request是这个类的对象
rest_framework.request.Request

2.虽然request已经变成drf提供的Request类的对象,但可以象之前一样使用
request.method>>>请求方式
request.path>>>/books/
request.GET>>>get请求提交的参数
request.POST>>>post请求提交的参数

3.Request的源码分析
3.1类中有__getattr__的魔法方法
# 如果取的值不存在会去原生django的request对象中取出来
def __getattr__(self, attr):
    try:
        # self._request是原来的request
        return getattr(self._request, attr)
    except AttributeError:
        return self.__getattribute__(attr)

'''
1.所有的属性或方法,可以直接通过反射去原来的request中取即可
2.新的request内部有原来的request,就是request._request
3.data是个方法,被property装饰了,变成数据属性用
-以后body体中提交的数据,都从这里取(request.POST)
-现在无论那种格式,都从request.data中取
-取文件从request.FILES中取,跟之前一样
'''

序列化组件

组件介绍

1.drf提供的一个类,我们继承它,写自己的类

2.序列化:格式化对象成我们要传递的数据
-使用for循环,列表套字典拼接

3.序列化类:drf提供了一种可以快速实现序列化的类

序列化的基本使用

定义序列化

from rest_framework import serializers


class BookSerializer(serializers.Serializer):
    # 要序列化字段
    name = serializers.CharField()  # 字段类
    price = serializers.CharField()
    publish = serializers.CharField()

视图类

from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
from .models import Book
class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        # instance是要序列化的数据,many=True表示序列化多条(如果instance是qs对象则一定要传many=True)
        ser = BookSerializer(instance=book_list, many=True)
        return Response(ser.data)


class BookDataView(APIView):
    def get(self, request, pk):
        # 获取单条数据
        book = Book.objects.filter(pk=pk).first()
        # instance是要序列化的数据,many=True表示序列化多条(如果instance是qs对象则一定要传many=True)
        ser = BookSerializer(instance=book)
        return Response(ser.data)

反序列化

前端传回的数据转成我的对象>>>新增、修改

新增(视图类)

def post(self, request):
    # 从request.data中取出前端传来的数据
    # 把前端传入的数据给data属性,来得到实例化得到ser对象
    ser = BookSerializer(data=request.data)
    # 校验前端传入的数据
    if ser.is_valid():
        # 保存这里会报错,
        ser.save()
        # 成功返回新增对象
        return Response(ser.data)
    else:
        # 失败返回错误信息
        return Response(ser.errors)

新增(序列化类)

from .models import Book
from rest_framework import serializers


class BookSerializer(serializers.Serializer):
    # 要序列化字段
    name = serializers.CharField()  # 字段类
    price = serializers.CharField()
    publish = serializers.CharField()
    # 重写create方法
    def create(self, validated_data):
        res = Book.objects.create(**validated_data)
        return res

修改(视图类)

def put(self, request, pk):
    # 获取单条数据
    book = Book.objects.filter(pk=pk).first()
    # instance是要序列化的数据,many=True表示序列化多条(如果instance是qs对象则一定要传many=True)
    ser = BookSerializer(instance=book, data=request.data)
    # 校验前端传入的数据
    if ser.is_valid():
        # 保存这里会报错,
        ser.save()
        # 成功返回新增对象
        return Response(ser.data)
    else:
        # 失败返回错误信息
        return Response(ser.errors)

修改(序列化类)

# 重写create
def update(self, instance, validated_data):
    instance.name = validated_data.get('name')
    instance.price = validated_data.get('price')
    instance.publish = validated_data.get('publish')
    instance.save()
    return instance

删除(视图类)

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

作业

1 继承apiview写5个接口()
class BookView(APIView):
    def get(self, request):
        # 获取所有数据
        book_list = Book.objects.all()
        res = []
        for book in book_list:
            res.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return HttpResponse(res)

    def post(self, request):
        name = request.data.get('name')
        price = request.data.get('price')
        publish = request.data.get('publish')
        Book.objects.create(name=name, price=price, publish=publish)
        return Response([{'name': name, 'price': price, 'publish': publish}])


class BookDataView(APIView):
    def get(self, request, pk):
        # 获取单条数据
        book = Book.objects.filter(pk=pk).first()
        res = []
        res.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return Response(res)

    def put(self, request, pk):
        name = request.data.get('name')
        price = request.data.get('price')
        publish = request.data.get('publish')
        Book.objects.filter(pk=pk).update(name=name, price=price, publish=publish)
        return Response([{'name': name, 'price': price, 'publish': publish}])

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

2 fbv写---》写个装饰器,装饰在视图函数,只要一装饰,以后的request就可以使用request.data,这个data无论是那种编码格式,都有数据
from django.shortcuts import HttpResponse
import json


def outer(func):
    def core(request, *args, **kwargs):
        if request.POST:
            request.data = request.POST
            res = func(request, *args, **kwargs)
            return res
        request.data = json.loads(request.body)
        res = func(request, *args, **kwargs)
        return res
    return core


@outer
def index(request):
    print(request.data)
    return HttpResponse('ok')

标签:return,name,APIView,self,request,book,组件,序列化,data
From: https://www.cnblogs.com/riuqi/p/16732946.html

相关文章