-
APIView的基本使用
drf:是一个第三方的app,只能在djagno上使用
安装了drf后,导入一个视图类APIView,所有后期要使用drf写视图类,都是继承APIView及其子类
例:获取所有图书接口
1.1使用View+JsonRessponse写
from django.views import View
from .models import Book
from django.http import JsonResponse
class BookView(View):
def get(self, request):
# print(type(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.1使用View+JsonRessponse写
记得在settings配置文件中注册rest_framemorkapp
from rest_framework.views import Response
from rest_framework.views import Request
from rest_framework.views import APIView
class BookView(APIView): #APIView继承自django的View
def get(self,request):
# print(type(self.request)) # 新的request
# print(type(request))
print(request._request)
print(type(request._request))
book_list = Book.objects.all()
# book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
res_list = []
for book in book_list:
res_list.append({'name': book.name,'price': book.price,'publish': book.publish})
return Response(res_list)
结果:
-
API源码分析
# 视图类继承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
-
APIView源码分析
#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)
-以后用的所有属性或方法,直接用就可以了---》(通过反射去原来的request中取的)
总结:
"""
drf的APIView类:
1.重写了as_view(),但主题逻辑还是调用父类view的as_view(),禁用了csrf认证(!所有继承drf的基本视图类APIView的视图类,都不做csrf认证校验)
2.重写了dispatch(),在内部对request进行了二次封装:
self.initialize_request(request, *args, **kwargs)
内部核心:
走drf的Request初始方法__init__:self._request = request
drf的Request的魔法方法__getattr__: 先从self.request反射取属性,没取到再向drf的request中取
"""
-
drf序列化组件
一.序列化组件介绍
1.序列化: 序列化器会把模型对象装换成字典,经过response以后变成json字符串
2.反序列化: 把客户端发送过来的数据进行数据校验,通过后经过request以后变成字典,序列化器可以把字典转成模型
二.简单使用步骤
1.写一个序列化类,继承Serializer
2.在类中写要序列化的字段,想序列化哪个字段,就在类中 写那个字段
3.在视图类中使用: 导入—> 实例化得到序列化类的对象,把要序列化的对象传入
4.序列化类的对象.data (字典)
5.把字典返回,如果不使用rest-framework提供的Response,就得使用JsonResponse
models.py
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish = models.CharField(max_length=32)
views.py
class BookView(APIView):
# def get(self,request,): # 序列化多条数据
# book_list = Book.objects.all()
def get(self,request,pk): # 序列化单条数据
book_list = Book.objects.filter(pk=pk).first
# instance表示要序列化的数据,many=True表示序列化多条数据
ser = BookSerializer(instance=book_list)
return Response(ser.data)
ser.py
class BookSerializer(serializers.Serializer):
# 要序列化的字段 有很多字段类型,字段类型有很多字段属性
# max_length 最大长度
# min_lenght 最小长度
# allow_blank 是否允许为空
# trim_whitespace 是否截断空白字符
# max_value 最小值
# min_value 最大值
name = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
url.py
from django.contrib import admin
from django.urls import path
from api.views import BookView
urlpatterns = [
path('admin/', admin.site.urls),
path('books', BookView.as_view()),
path('books/<int:pk>/',BookView.as_view())
]
-
反序列化(增删改查)
新增
view.py
class BookView(APIView):
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)
models.py
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
修改
view.py
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)
models.py
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
查询所有
view.py
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,many=True)
models.py
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish = models.CharField(max_length=32)
查一本
view.py
class BookView(APIView):
def get(self, request,pk):
book_list = Book.objects.filter(pk=pk).first()
res_list = []
for book in book_list:
res_list.append({'name': book.name, 'price':book.price, 'publish':book.publish})
return Response(res_list)
删除
view.py
class BooksView(APIView):
def delete(self,request,pk):
res = Book.objects.filter(pk=pk).delete()
return Response({'status': 1000, 'msg': '删除成功'})
标签:改查,self,request,list,book,增删,序列化,APIView
From: https://www.cnblogs.com/tai-yang77/p/16732629.html