drf-day02

1 APIView基本使用

drf:是一个第三方的app,只能在djagno上使用
安装了drf后,导入一个视图类APIView,所有后期要使用drf写视图类,都是继承APIView及其子类

1.1 使用View+JsonResponse写

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


#
# class BookView(View):
#     def get(self,request):
#
#         book_list=Book.objects.all()
#         res_list=[]
#         for book in book_list:
#             res_list.append({'name':book.name,'price':book.price,'publish':book.publish})
#         return JsonResponse(res_list,safe=False,json_dumps_params={'ensure_ascii':False})

1.2 使用APIView+drf的Response写

注册rest_framework

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    'rest_framework'
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request


class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        res_list = []
        for book in book_list:
            res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return Response(res_list)

在这里插入图片描述

2 APIView源码分析

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

# 一旦继承了APIView入口
	-路由配置跟之前继承View是一样的----》找视图类的as_view---》【APIView的as_view】
        @classmethod
        def as_view(cls, **initkwargs):
            # 又调用了父类(View)的as_view
            view = super().as_view(**initkwargs)
            '''
            # 从此以后,所有的请求都没有csrf的校验了
            # 在函数上加装饰器
            @csrf_exempt
            def index(request):
                pass
            本质等同于 index=csrf_exempt(index)
            '''
            return csrf_exempt(view)
        
    -请求来了,路由匹配成功会执行 View类的的as_view类方法内的view闭包函数(但是没有了csrf认证)-真正的执行,执行self.dispatch---->APIView的dispatch  【这是重点】
     def dispatch(self, request, *args, **kwargs):
        # 参数的request是原来的django原生的request
        # 下面的request,变成了drf提供的Request类的对象---》return Request(。。。)
        request = self.initialize_request(request, *args, **kwargs)
        # self 是视图类的对象,视图类对象.request=request 新的request
        self.request = request
        try:
            # 执行了认证,频率,权限 [不读]
            self.initial(request, *args, **kwargs)
            # 原来的View的dispatch的东西
            if request.method.lower() in self.http_method_names:
                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 执行视图类的方法之前,执行了3大认证(认证,权限,频率)
    4 在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理

3 Request类源码分析

1 视图类中使用的request对象,已经变成了drf提供的Request类的对象了

-原生djagno 的request是这个类的对象:django.core.handlers.wsgi.WSGIRequest
-drf的request是这个类的对象:rest_framework.request.Request

2 request已经不是原来的request了,还能像原来的request一样使用吗? -用起来,像之前一样

    print(request.method)  # get
    print(request.path)  # /books/
    print(request.GET)   # 原来的get请求提交的参数
    print(request.POST)  # 原来post请求提交的参数

3 Request的源码分析:rest_framework.request.Request

类中有个魔法方法:__getattr__    对象.属性,属性不存在会触发它的执行
def __getattr__(self, attr): # 如果取的属性不存在会去原生django的request对象中取出来
    try:
        #反射:根据字符串获取属性或方法,self._request 是原来的request
        return getattr(self._request, attr)
    except AttributeError:
        return self.__getattribute__(attr)

-data 是个方法,被property装饰了,变成了数据属性用
-1.以后body体中提交的数据,都从这里取(request.POST)
-2.urlencoded,form-data:提交的数据在request.POST中
-3.json格式提交的数据,在requets.POST中没有,它在request.body中
-4.现在无论那种格式,都从request.data中取
-query_params:get请求提交的参数,等同于request._request.GET 或 request.GET
-其他:取文件也是从request.FILES中取,跟之前一样

4 什么是魔法方法?

1 在类中只要以__开头,__结尾的都称之为魔法方法
2 这种方法不需要手动调用,某种情况会自动触发
3 你学过的: __init__,__str__,__call__,......

4 序列化组件基本使用(查询所有,查询单个)

是什么?drf提供的一个类,我们继承它,写自己的类

有什么用?就是用来序列化qs或单个对象的

获取所有图书接口----》qs,单个book对象转成json格式字符串,给前端—》序列化
-使用for循环,列表套字典拼接的

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

1 定义一个序列化类

from rest_framework  import serializers
from app01.models import Book



# 写序列化类:给book进行序列化

class BookSerializer(serializers.Serializer):
    # 要序列化的字段    有很多字段类,字段类有很多字段属性
    name=serializers.CharField()   # 字段类
    price = serializers.CharField()
    publish = serializers.CharField()
   

4.2 使用序列化类,序列化多条数据

class BookView(APIView):  # APIView继承自django的View
    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)

4.3 使用序列化类,序列化单挑数据

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




from django.contrib import admin
from django.urls import path
from app01.views import BookView
from app01.views import BookDetailView
urlpatterns = [
    # path('admin/', admin.site.urls),
    # path('books/',BookView.as_view()),
    path('books/<int:pk>/', BookDetailView.as_view())
]

5 反序列化(新增,修改)

5.1新增视图类

class BookView(APIView):  # APIView继承自django的View
    def post(self, request):
        # 前端传递数据,从request.data取出来
        ser = BookSerializer(data=request.data)
        if ser.is_valid():  # 表示校验前端传入的数据   没有写校验规则,现在等于没校验
            ser.save()  # 再写东西,这里会报错  调用save会触发BookSerializer的save方法,判断了,如果instance有值执行update,没有值执行create
            return Response(ser.data)
        else:
            return Response(ser.errors)

5.2 序列化类

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

5.3修改视图类

class BookDetailView(APIView):
    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        # 前端传递数据,从request.data取出来
        ser = BookSerializer(instance=book, data=request.data)
        if ser.is_valid():  # 表示校验前端传入的数据   没有写校验规则,现在等于没校验
            ser.save()  # 再写东西,这里会报错  调用save会触发BookSerializer的save方法,判断了,如果instance有值执行update,没有值执行create
            return Response(ser.data)
        else:
            return Response(ser.errors)

5.4序列化类

class BookSerializer(serializers.Serializer):
    # 要序列化的字段    有很多字段类,字段类有很多字段属性
    name = serializers.CharField()  # 字段类
    price = serializers.CharField()
    publish = serializers.CharField()

    # 重写update
    def update(self, instance, validated_data):
        # 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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值