drf的使用

APIView

  • drf: 第三方的app,只能在django上使用(不同版本对django的版本有所要求)
  • drf安装后,导入一个视图类APIView
  • 使用drf写视图类要继承APIView及其子类

基本使用

使用View+JsonResponse与APIView+drf对比

  1. View+JsonResponse
from django.views import View
from .models import Book

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. APIView+drf
    • 不要忘了注册rest_framework这个app
from .models import Book
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)

源码分析

  • 视图类继承APIView后,执行流程发生了变化,此变化就是整个的drf的执行流程
  • 从参数得APIView入手

APIView --> as_view -->super().as_view–> self.dispatch–>dispatch
APIView --> as_view -->csrf_exempt

@csrf_exempt
def index(request):
本质等同于 index=csrf_exempt(index)

# 请求来了,路由匹配成功后执行
def dispatch(self, request, *args, **kwargs):
        # 参数的request是原来的django原生的request
        # 下面的request,变成了drf提供的Request类的对象---》return Request(。。。)

总结:

  1. 继承APIView后都没有csrf的认证了
  2. 以后视图类中使用的request对象,已经变成了drf提供的Request对象了
  3. 执行视图类的方法前,执行了三大认证(认证,权限,频率)
  4. 在执行三大认证和视图类的方法过程报错,直接使用异常捕获

Request类源码分析

  1. 视图类内的request对象已被drf内的Request对象替换

原生django的request对象是
(django.core.handlers.wsgi.WSGIRequest)类的
drf的request对象是
(rest_framework.request.Request)类的

  1. request虽然不是原来的当仍然可以使用
   print(request.method)  # get
   print(request.path)  # /books/
   print(request.GET)   # 原来的get请求提交的参数
   print(request.POST)  # 原来post请求提交的参数
  1. Request源码
    # from rest_framework.request import 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)        
    
  1. 新的request内部有一个老的request,是request._request
  2. data是方法,被property装饰后,变为了数据属性
  3. 以后body体中提交的数据,都从这里取(request.POST)
  4. 取文件也是从request.FILES中取
  5. query_params:get请求提交的参数,等同于request._request.GET 或 request.GET
    “”"
    -以后body体中提交的数据,都从这里取(request.POST)
    -urlencoded,form-data:提交的数据在request.POST中
    -json格式提交的数据,在requets.POST中没有,它在request.body中
    -现在无论那种格式,都从request.data中取
    “”"
  1. 魔法方法? __开头,__结尾

序列化

序列化组件

  • 序列化组件时就是,drf提供的一个类,我们通过继承它,重写自己的类
  • drf提供了一种可以快速实现序列化的类:序列化类

定义一个序列化类

# serializer.py
from .models import Book
from rest_framework import serializers

class BookSerializer(serializers.Serializer):

    name= serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()
# views.py
from django.http import JsonResponse
from .models import Book
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
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):
        print(request.data)
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)
class BookDetailView(APIView):
    # 序列化单条
    def get(self,request,pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        return Response(ser.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(ser.data)
        else:
            return Response(ser.errors)
    # 删除
    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response()
# serializer.py
from .models import Book
from rest_framework import serializers

class BookSerializer(serializers.Serializer):

    name= serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()
    
    def create(self,validated_data):
        res = Book.objects.create(**validated_data)
        return res

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

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

使用序列化类,序列化单条数据

反序列化

使用反序列化类,新增与修改

新增

修改

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

from django.http import JsonResponse
def out_view(func_name):
    def inner(request, *args, **kwargs):
        request = APIView().initialize_request(request)
        res = func_name(request, *args, **kwargs)
        return res
    return inner

# @csrf_exempt
@ out_view
def index(request):
    ser = BookSerializer(data=request.data)
    if ser.is_valid():
        ser.save()
        return JsonResponse(ser.data)
    else:
        return JsonResponse(ser.errors)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值