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