drf从入门到飞升仙界 03
APIView执行流程
基于APIView+JsonResponse编写接口
# APIView是drf提供给使用者的一个类,在使用drf写视图类,继承都是这个类及其子类
# APIView继承了Django原生的view # 要注意写路由
# 使用APIView查所有
from django.shortcuts import render
from rest_framework.views import APIView
from .models import Books
from django.http import JsonResponse
# Create your views here. class BookView(APIView):
def get(self,request):
books = Books.objects.all()
book_list = []
for book in books:
book_list.append({'name':book.name,'price': book.price,'publish': book.publish})
return JsonResponse(book_list,safe=False)
基于APIView+Response写接口
from rest_framework.response import Response
# drf的Response无论是列表还是字典都可以序列化 class BookView(APIView):
def get(self,request):
books = Books.objects.all()
book_list = []
for book in books:
book_list.append({'name':book.name, 'price': book.price, 'publish': book.publish})
return Response(book_list)
APIView的执行流程
# 1.路由中写:
path('books/', views.BookView.as_view()),
# 2.请求来了先执行views.BookView.as_view()()
现在的as_view是drf中APIView的as_view
# 3.APIView的as_view方法:view还是django原生的view,但是没有csrf认证了
@classmethod
def as_view(cls, **initkwargs):
# 调用了父类的as_view,父类是django原生的View
# 把django原生view的as_view方法中的闭包函数view拿出来了
view = super().as_view(**initkwargs)
return csrf_exempt(view)
# 4.路由匹配成功,执行csrf_exempt(view)(requets)
# 5.view的as_view中的闭包函数view>>>self.dispatch
# 6.self.dispatch,self是视图类的对象>>>Bookview
# 7.APIView的dispatch
def dispatch(self,request,*args,**kwargs):
# request是django原生的request
# 把原生的request包装成新的request,这个是drf提供的Request类的对象
request = self.initialize_request(request, *args, **kwargs)
# 到此,request是新的,request._request是老的
# 把新的request放到了self对象[BookView的对象]
self.request = request
try:
# 执行了三大认证【认证,频率,权限】,使用新的request,不读
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
# 把新的request传入了,视图类的方法中get的request也是新的
response = handler(request, *args, **kwargs) except Exception as exc:
# 在执行3大认证和视图类中方法的过程中,如果出了异常,都能捕获到---》全局异常捕获
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response # APIView的执行流程总结
-1.去除了所有的csrf
-2.包装了新的request.以后·再视图类中用的request是新的。而Request类的对象也是新的,原生的Request类对象再新的request._request
-3.在执行视图类的方法之前,执行了3大认证
-4.如果3大认证或视图函数方法执行过程中出了错,会有异常捕获>>>全局异常捕获
-5.以后视图类方法中的request都是新的 # 补充:装饰器的基本原来
def auth() # 装饰器
def add() # 函数 # 使用auth装饰add函数
@auth # 本质是 add=auth(add)
def add() # 以后再使用add,其实就是在使用 auth(add) 的返回结果
Request对象源码分析
# 老的Request导入:
django.core.handlers.wsgi.WSGIRequest
# 新的Request导入:
from rest_framework.request import Request
# request._request是老的 # Request源码
-方法 __getattr__
在视图类的方法中,执行request.method,新的request是没有method,所以就会触发新的Request的__getattr__方法的执行
def __getattr__(self,attr):
try:
# 从老的request中反射出要取得的属性
return getattr(self._request,attr)
except AttributeError:
return self.__getattribute__(attr)
-request.data : 这是个方法,包装成了数据属性
以后无论post,put..,放在body中提交的数据,都从request。data中取,取出来就是字典,不管是哪种编码格式
-request.query_params : 这是个方法,包装成了数据属性
get请求携带的参数,以后从这里面取
query_params:查询参数(restful规范请求地址中带查询参数)
-request.FilES: 这是个方法,包装成了数据属性
前端提交过来的文件,从这里取 # Request类总结
-1.新的request用起来,和之前一样。是因为,新的取不到,会在老的__getattr__取
-2.request.data 无论什么编码。什么请求方式,只要是body中的数据,就从这里取,字典
-3.request.query_params 就是原来的request._request.GET
-4.上传的文件从request.FILES # python中的魔法方法。在类中某种情况下会触发,会自动执行
__str__ :打印对象会调用
__init__:类() 会调用
__call__:对象() 会调用
__getattr__: 对象.属性,如果属性不存在,会触发它的执行
序列化器介绍和快速使用
# 1.我们写接口时,需要序列化,也需要反序列化,并且反序列化的过程中需要做数据校验,drf则直接提供多个固定的写法,只要按照drf固定的写法使用,就能完成上面三个需求 # 2.提供了两个类 Serializer ModelSerializer
我们只需要写自己的类,继承drf提供的序列化类,使用其中的某些方法,就能完成上面的操作
# 3.使用APIView+序列化类+Response完成接口的编写
-1.序列化类基本使用,序列化多条
# serializer.py
- BookSerializer类
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
# 序列化某些字段,这里写要序列化的字典
name = serializers.CharField()
publish = serializers.CharField() # views.py
- BookView类
class BookView(APIView):
def get(self,request):
print(request.method)
print(request._request)
print(type(self.request))
books = book.objects.all()
# 使用序列化类来完成——>得有个序列化类
# instance要序列化的数据books queryset对象
# many=True 只要是queryset对象,要传many=True, 如果是单个对象就不用传
ser = BookSerializer(instanse=books,many=True)
return Response(ser.data) # 无论是列表还是字典都可以序列化
-2.序列化单条
# 1.序列化类---没有动
from rest_framework import serializers class BookSerializer(serializers.Serializer):
# 序列化某些字段,这里写要序列化的字典
name = serializers.CharField() # serializers下大致跟models下的类是对应的
# price = serializers.CharField()
publish = serializers.CharField() # 2.视图类---》BookDetailView
class BookDetailView(APIView):
# def get(self, request,pk):
def get(self, request, *args, **kwargs):
book = Book.objects.filter(pk=kwargs.get('pk')).first()
# 序列化
ser = BookSerializer(instance=book)
return Response(ser.data) # 3.url加了新的路由
urlpatterns = [
path('books/<int:pk>/', views.BookDetailView.as_view()),
]
反序列化
反序列化的新增
# 序列化类
class BookSerializer(serializers.Serializer):
# 序列化某些字段,这里写要序列化的字典
name = serializers.CharField() # serializers下大致跟models下的类是对应的
price = serializers.CharField()
publish = serializers.CharField() def create(self, validated_data):
# 保存的逻辑
# validated_data 校验过后的数据 {name,price,publish}
# 保存到数据库
book = Book.objects.create(**validated_data)
# 一定不要返回新增的对象
return book # 视图类
class BookView(APIView):
def post(self, request):
# requset.data # 前端提交的要保存的数据----》校验数据---》存
ser = BookSerializer(data=request.data) # 把前端传入的要保存的数据,给data参数
# 校验数据
if ser.is_valid():
# 保存---->需要自己写,要在序列化类BookSerializer中写----》create方法
ser.save() # 调用ser.save,自动触发咱们写的create,保存起来
return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
反序列化的修改
# 序列化类
class BookSerializer(serializers.Serializer):
# 序列化某些字段,这里写要序列化的字典
name = serializers.CharField() # serializers下大致跟models下的类是对应的
price = serializers.CharField()
publish = serializers.CharField() def create(self, validated_data):
# 保存的逻辑
# validated_data 校验过后的数据 {name,price,publish}
# 保存到数据库
book = Book.objects.create(**validated_data)
# 一定不要返回新增的对象
return book 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() # orm的单个对象,修改了单个对象的属性,只要调用对象.save,就能把修改保存到数据库 return instance # 不要忘了吧修改后的对象,返回 # 视图类
class BookDetailView(APIView): def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
# 反序列化保存 ---借助于序列化类
ser = BookSerializer(data=request.data, instance=book)
if ser.is_valid():
ser.save() # 由于没有重写update,所以这报错
return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
删除单条
class BookDetailView(APIView): def delete(self, requset, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})
基于序列化器编写5个接口
反序列化的校验
class BookSerializer(serializers.Serializer):
# 序列化某些字段,这里写要序列化的字典
name = serializers.CharField() # serializers下大致跟models下的类是对应的
price = serializers.CharField()
publish = serializers.CharField() def create(self, validated_data):
# 保存的逻辑
# validated_data 校验过后的数据 {name,price,publish}
# 保存到数据库
book = Book.objects.create(**validated_data)
# 一定不要返回新增的对象
return book 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() # orm的单个对象,修改了单个对象的属性,只要调用对象.save,就能把修改保存到数据库 return instance # 不要忘了吧修改后的对象,返回 # 反序列化校验的局部钩子 ,名字不能以sb开头
def validate_name(self, name):
# 校验name是否合法
if name.startswith('sb'):
# 校验不通过,抛异常
raise ValidationError('不能以sb开头')
else:
return name # 全局钩子
def validate(self, attrs):
# 校验过后的数据,书名跟出版社名字不能一致
if attrs.get('name') == attrs.get('publish'):
raise ValidationError('书名跟出版社名字不能一致')
else:
return attrs
drf从入门到飞升仙界 03的更多相关文章
- 【Lucene3.6.2入门系列】第03节_简述Lucene中常见的搜索功能
package com.jadyer.lucene; import java.io.File; import java.io.IOException; import java.text.SimpleD ...
- php从入门到放弃系列-03.php函数和面向对象
php从入门到放弃系列-03.php函数和面向对象 一.函数 php真正的威力源自它的函数,内置了1000个函数,可以参考PHP 参考手册. 自定义函数: function functionName( ...
- 098 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 02 编写并测试Subject类
098 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 02 编写并测试Subject类 本文知识点:编写并测试Subject类 说明: ...
- 099 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 03 编写并测试Student类
099 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 03 编写并测试Student类 本文知识点:编写并测试Subject类 说明: ...
- 101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联——方案二
101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联--方案二 本文知识点:通过方法实现学生类与 ...
- Docker从入门到飞升:基础配置安装
导读 Docker近几年非常火,因为它是容器虚拟化,更能够充分提高硬件资源的使用率.其实利用率高不算什么,它最大的优势是能给让运维人员或者开发人员快速部署和交付资源,大大提高了工作效率.几乎所有的大企 ...
- Linux性能优化从入门到实战:03 CPU篇:CPU上下文切换
linux操作系统是将CPU轮流分配给任务,分时执行的.而每次执行任务时,CPU需要知道CPU寄存器(CPU内置的内存)和程序计数器PC(CPU正在执行指令和下一条指令的位置)值,这些值是CPU执 ...
- 【原创】新手用外挂来学C语言,外挂入门教程【2013.03.12更新V5.1版
目录 e@vZg8Ie 第一章 配置编译环境 - 5 - W7~_XI 1.1 安装CB和gcc - 6 - fj( WH L 1.2 使用gcc编写我们的第一个C程序 - 1 ...
- opengl入门学习
OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640 ...
- npm使用入门(package.json)
npm使用入门 crazygit 关注 2017.03.10 18:31 字数 1773 阅读 1617评论 0喜欢 10 NPM是什么 npm npm makes it easy for JavaS ...
随机推荐
- pgsql判断字符串是否为数字
利用正则表达式来对字符串进行匹配 因为工作遇到了一个问题需要对字符串是否可以转换为数值进行判断.今天关于这个问题进行一个分享,流程如下 数字的正则表达式 ^([0-9]+.?[0-9]*|.[0-9] ...
- 第4关—input()函数
1.input()函数 input()函数是输入函数 import time print('亲爱的同学:') time.sleep(1) print('我们愉快地通知您,您已获准在霍格沃茨魔法学校就 ...
- Kubernetes 设置master相关
设置master调度命令 1.设置master一般情况下不接受pod调度 sudo kubectl taint nodes master node-role.kubernetes.io/master= ...
- Docker 对于容器的增删查命令
列出所有容器 ID 1 docker ps -aq 停止所有容器 1 docker stop $(docker ps -aq) 停止单个容器 1 docker stop 要停止的容器名 删除所有容器 ...
- 超级详细的Vue安装与配置教程
原文: https://www.jb51.net/article/251371.htm 超级详细的Vue安装与配置教程 Vue web前端三大主流框架之一,是一套用于构建用户界面的渐进式框架,下面 ...
- React函数式组件值之useRef()和useImperativeHandle()
一.useRef useRef共有两种用法,获取子组件的实例(只有类组件可用),在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx. 1. useRe ...
- 「SOL」Quick Tortoise (Codeforces)
只能说没想到 题面 给出一个 \(n\times m\) 的网格图,每个格子要么是空地要么是障碍. 给出 \(q\) 个询问,每次给出 \((sx, sy),(ex,ey)\),问从 \((sx,sy ...
- Windows流媒体怎么关闭。
点击白色框,搜索服务. 步骤阅读 步骤阅读 2 选本地服务旁打开,然后下拉服务. 步骤阅读 步骤阅读 3 选择media,然后右键它属性. 步骤阅读 步骤阅读 4 然后点击停止,点击手动. 步骤阅读 ...
- 51电子-STC89C51开发板:回忆
全部内容,请点击: 51电子-STC89C51开发板:<目录> --------------------------- 正文开始 --------------------------- ...
- 【java数据结构与算法】插入排序
[插入排序解析]起始:假设第一个元素为已经排好序那么我们就要从数组的第二个元素开始每一轮确定1一个元素的正确位置所以外层循环的控制变量为 [1,arr.length)的左闭右开区间外层循环控制比较轮次 ...