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
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源码分析
-路由配置跟之前继承View是一样的----》找视图类的as_view---》【APIView的as_view】
@classmethod
def as_view(cls, **initkwargs):
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 = self.initialize_request(request, *args, **kwargs)
self.request = request
try:
self.initial(request, *args, **kwargs)
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
class BookSerializer(serializers.Serializer):
name=serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
4.2 使用序列化类,序列化多条数据
class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
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('books/<int:pk>/', BookDetailView.as_view())
]
5 反序列化(新增,修改)
5.1新增视图类
class BookView(APIView):
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
5.2 序列化类
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
5.3修改视图类
class BookDetailView(APIView):
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)
5.4序列化类
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
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
|