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的更多相关文章

  1. 【Lucene3.6.2入门系列】第03节_简述Lucene中常见的搜索功能

    package com.jadyer.lucene; import java.io.File; import java.io.IOException; import java.text.SimpleD ...

  2. php从入门到放弃系列-03.php函数和面向对象

    php从入门到放弃系列-03.php函数和面向对象 一.函数 php真正的威力源自它的函数,内置了1000个函数,可以参考PHP 参考手册. 自定义函数: function functionName( ...

  3. 098 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 02 编写并测试Subject类

    098 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 02 编写并测试Subject类 本文知识点:编写并测试Subject类 说明: ...

  4. 099 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 03 编写并测试Student类

    099 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 03 编写并测试Student类 本文知识点:编写并测试Subject类 说明: ...

  5. 101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联——方案二

    101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联--方案二 本文知识点:通过方法实现学生类与 ...

  6. Docker从入门到飞升:基础配置安装

    导读 Docker近几年非常火,因为它是容器虚拟化,更能够充分提高硬件资源的使用率.其实利用率高不算什么,它最大的优势是能给让运维人员或者开发人员快速部署和交付资源,大大提高了工作效率.几乎所有的大企 ...

  7. Linux性能优化从入门到实战:03 CPU篇:CPU上下文切换

      linux操作系统是将CPU轮流分配给任务,分时执行的.而每次执行任务时,CPU需要知道CPU寄存器(CPU内置的内存)和程序计数器PC(CPU正在执行指令和下一条指令的位置)值,这些值是CPU执 ...

  8. 【原创】新手用外挂来学C语言,外挂入门教程【2013.03.12更新V5.1版

    目录 e@vZg8Ie  第一章 配置编译环境    - 5 - W7~_XI  1.1 安装CB和gcc    - 6 - fj( WH L  1.2 使用gcc编写我们的第一个C程序    - 1 ...

  9. opengl入门学习

    OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640 ...

  10. npm使用入门(package.json)

    npm使用入门 crazygit 关注 2017.03.10 18:31 字数 1773 阅读 1617评论 0喜欢 10 NPM是什么 npm npm makes it easy for JavaS ...

随机推荐

  1. ubuntu 安装php7.2 oracle扩展

    一:介绍 php要连接访问oracle需要安装三个东西 1:Oracle Instant Client:即时客户端库 2:php的Oracle数据库扩展:oci8 3:php连接pdo的oci扩展:p ...

  2. 重写Collections集合的排序比较CompareTo方法

    Collections.sort()使用该方法实际是重写Comparator接口的compare方法实现排序: //传入参数list集合,Comparator接口 T:list的元素类型 //如Lis ...

  3. taro 学习笔记

    1.Taro 是一个开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发 微信 / 京东 / 百度 / 支付宝 / 字节跳动 / QQ / 飞书 小程序 / H5 / RN ...

  4. Java_类与对象

    类与对象 概念 类是抽象的,概念的,代表一类事物,比如人类.猫类--,即它是数据类型. 对象是具体的,实际的,代表一个具体事物,即使实例. 类是对象的模板,对象是类的一个个体,对应一个实例 对象在内存 ...

  5. idea等工具网盘下载地址

    1.idea2020 下载地址:https://caiyun.139.com/m/i?1E5C2SkIZbJH4 ,下载密码微信 搜索 "白菜拼吧" 回复 idea2020 获取 ...

  6. linux中用crontab定时任务启动jar无效

    修改前脚本内容如下: #!/bin/bash nohup java -Xms512m -Xmx512m -jar /opt/jar/xx-0.0.1-SNAPSHOT.jar & 检查了各方面 ...

  7. 21_webpack_DDL

    DLL库(不再使用) DLL全称是动态链接库(Dynamic Link Library),是为软件在Windows中实现共享函数库的一种实现方式 webpack中也有内置DLL的功能,它指的是我们可以 ...

  8. tool script to convert back slash

    Back slash is used in windows, which makes so many headache for me. Then an idea came to my mind. It ...

  9. 14-K8S之helm入门到逃跑

    目录 helm入门 1.helm介绍 2.helm核心术语 3.helm下载和安装 3.1以helm3.6为测试实例 3.2以helm3.7.2为例 helm v2版本在集群上部署Tiller 1.创 ...

  10. IMX6Ull驱动

    mount -t nfs -o nolock,vers=3 192.168.1.117:/home/book/nfs_rootfs /mnt cat /proc/sys/kernel/printk e ...