drf(初始drf,restfull规范 ,CBV、APIView、Request源码)
一 web开发模式
# 前后端混合开发(前后端不分离):通过模版语法,在服务器上处理好html的内容(组合字符串),返回给浏览器一堆字符串(字符串封装到respons对象里),浏览器在渲染 # 前后端分离:只专注于写后端接口,返回json、xml格式
# xml比json笨重 # 补充:什么是动态页面(需要查数据库的),什么是静态页面(内容写死的页面)
# 访问量大的home页面,进行静态页面优化
二 API接口
# 通过网络,规定了前后台信息交互规则的url链接,也就是前后台信息交互的媒介
Application Programming Interface
三 postman的使用
# postman是当前最好用的,模拟发送http请求的工具
# 解析json的网站
www.json.cn # 请求头中User-Agent:客户端的类型
# 请求头中加其他参数
# url的末尾加/,浏览器中不加,是因为两次get,重定向自动给加上去的
四 restfull规范
'''
1. 什么是RESTFUll RESTfull 是目前最流行的 API 设计规范,用于 Web 数据接口的设计。 REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
'''
十条规范
1 数据的安全保障
url链接一般都采用https协议进行传输
注:采用https协议,可以提高数据交互过程中的安全性
抓包工具:fiddler,chales
2 接口特征表现
用api关键字标识接口url:
注:看到api字眼,就代表该请求url链接是完成前后台数据交互的
3 多数据版本共存
在url链接中标识数据版本
注:url链接中的v1、v2就是不同数据版本的体现(只有在一种数据资源有多版本情况下)
就比如手机app,有 些升级了,有些还没升级,没升级的,就是用的老版本
新升级的,用的新版本
4 数据即是资源,均使用名词(可复数)
接口一般都是完成前后台数据的交互,交互的数据我们称之为资源
注:一般提倡用资源的复数形式,在url链接中奖励不要出现操作资源的动词,错误示范:https://api.baidu.com/delete-user
特殊的接口可以出现动词,因为这些接口一般没有一个明确的资源,或是动词就是接口的核心含义
5 资源操作由请求方式决定
操作资源一般都会涉及到增删改查,我们提供请求方式来标识增删改查动作
https://api.baidu.com/books - get请求:获取所有书
https://api.baidu.com/books/1 - get请求:获取主键为1的书
https://api.baidu.com/books - post请求:新增一本书书
https://api.baidu.com/books/1 - put请求:整体修改主键为1的书
https://api.baidu.com/books/1 - patch请求:局部修改主键为1的书
https://api.baidu.com/books/1 - delete请求:删除主键为1的书
6 过滤信息(filtering,或称查询参数)
如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。下面是一些常见的参数。
https://api.baidu.com/v1/books?limit=10:指定返回记录的数量
https://api.baidu.com/v1/books?offset=10:指定返回记录的开始位置。
https://api.baidu.com/v1/books?page=2&per_page=100:指定第几页,以及每页的记录数。
https://api.baidu.com/v1/books?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
https://api.baidu.com/v1/books?animal_type_id=1:指定筛选条件
7.响应状态码
7.1 正常响应
响应状态码2xx
200:常规请求
201:创建成功
7.2 重定向响应
响应状态码3xx
301:永久重定向
302:暂时重定向
7.3 客户端异常
响应状态码4xx
403:请求无权限
404:请求路径不存在
405:请求方法不存在
7.4 服务器异常
响应状态码5xx
500:服务器异常
8 错误处理,应返回错误信息,error当成key
发生错误时不要响应200状态码,有一种不恰当的做法是,即使发生错误,也返回200
状态码,把错误信息放在数据体里面,就像下面这样。
{
"status": "failure",
"data": {
"error": "Expected at least two items in list."
}
}
9 返回结果,针对不同操作,服务器向用户返回的结果应该符合一下规范
GET /collection:返回资源对象的列表(数组),一般是[{"id":1,"name":"a",},{"id":2,name:"b"},]这种类型
GET /collection/resource:返回单个资源对象, 一般是查看的单条数据 {"id":1,"name":'a'}
POST /collection:返回新生成的资源对象 , 一般是返回新添加的数据信息, 格式一般是{}
PUT /collection/resource:返回完整的资源对象 一般时返回更新后的数据,{}
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档 一般返回一个空字符串
10 Hypermedia API,提供链接
RESTful API最好做到Hypermedia,即返回结果中提供链接,API 的使用者未必知道,URL 是怎么设计的。
一个解决方法就是,在回应中,给出相关链接,便于下一步操作。
这样的话,用户只要记住一个 URL,就可以发现其他的 URL。
{
...
"feeds_url": "https://api.github.com/feeds",
"followers_url": "https://api.github.com/user/followers",
"following_url": "https://api.github.com/user/following{/target}",
"gists_url": "https://api.github.com/gists{/gist_id}",
"hub_url": "https://api.github.com/hub",
...
}
五 drf的安装和简单使用
# 安装:pip install djangorestframework=3.10.3
# 使用:
1 在settings.py
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'
]
2 在models.py中写表模型
class Book(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
author = models.CharField(max_length=32)
3 新建一个序列化类
app01下建一个ser.py
from rest_framework.serializers import ModelSerializer
from app01.models import Book class BookModelSerializer(ModelSerializer):
class Meta:
model = Book
fields = "__all__"
4 在视图函数中写视图类,views.py
from rest_framework.viewsets import ModelViewSet
from app01.models import Book
from app01.ser import BookModelSerializer # Create your views here.
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerializer 5 写路由关系,urls.py
from app01 import views
from rest_framework.routers import DefaultRouter router = DefaultRouter() # 可以处理视图的路由器
router.register('book', views.BookViewSet) # 向路由中注册视图集 # 将路由中的所有路由信息追到django的路由列表中 urlpatterns = [
path('admin/', admin.site.urls),
] # 两个列表相加,就是将列表rooter.urls的值追加到urlpatterns,for循环,再.append
urlpatterns += router.urls
六 CBV源码
# ModelViewSet继承View(django原生View)
# APIView继承View # 先读View
# views.py
from django.views import View
class Books(View):
def get(self, request):
return HttpResponse('ok') # urls.py
path('books/', views.Books.as_view()),
'''
在这个地方应该写个函数的内存地址,views.Books.as_view()执行完,是个函数内存地址,Books继承了Views类,里面的as_view是类方法,所有由Books.as_view()
'''
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] '''
因return view,view是as_view的闭包函数,Books.as_view()的调用,就是调用view,类的绑定方法,把类当对象传入。
'''
@classonlymethod
# 路由中,一般没有传参, **initkwargs没有值
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs) # 实例化,book对象
self.setup(request, *args, **kwargs)
return self.dispatch(request, *args, **kwargs)
# dispatch方法,先对象里找,没有去类中找,类中没有就去给类的父类找
return view def setup(self, request, *args, **kwargs):
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
# 传入的request,赋值给对象
self.request = request def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names:
# 反射取值,得到get的内存地址
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
# 内存地址加括号并传参,就是传参调用函数
return handler(request, *args, **kwargs)
七 APIView源码
1 一切皆对象
函数也是对象
def foo(a,b):
return a+b foo.name = 'lq' # 一切皆对象 print(foo(2,3)) print(foo.name) # lq’
2 局部禁用csrf
# 在视图函数上加装饰器@csrf_exempt
# csrf_exempt(view) 这么写和在视图函数上加装饰器是一模一样
3 源码
# urls.py
path('booksapiview/', views.BooksAPIView.as_view()) # views.py
from rest_framework.views import APIView
class BooksAPIView(APIView):
def get(self, request):
return HttpResponse('ok') # APIView的as_view方法(类的绑定方法)
@classmethod
def as_view(cls, **initkwargs):
# 调用父类,就是django的View类的as_view方法
view = super().as_view(**initkwargs)
# 把函数当对象,进行属性赋值
view.cls = cls
view.initkwargs = initkwargs
# Note: session based authentication is explicitly CSRF validated,
# 以后所有的请求,都没有csrf认证了,只要继承了APIView,就没有csrf的认证
# all other authentication is CSRF exempt.
# 就是给函数加装饰器@csrf_exempt
return csrf_exempt(view) # view = super().as_view(**initkwargs),--->django的View类中的as_view方法--->return self.dispatch(request, *args, **kwargs)--->回到APIView类的dispatch方法 # 类的方法调用,先从对象找--->产生对象的类中找--->父类--->父类的父类 def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 重新包装成一个request对象,以后再用的request对象,就是新的request对象了,initialize_request,是Request类的一个实例化的返回
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate? try:
# 三大认证模块(request是新的request)
self.initial(request, *args, **kwargs) # Get the appropriate handler method
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)
# 渲染模块,根据客户端的不同(浏览器,postman),渲染不同的数据
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
Request类的源码
# from rest-framework.request import Request
# 只要继承了APIView,视图类中的request对象,都是新,也就是上面新的self.initialize_request(request, *args, **kwargs)
# 原生的request在新的request._request class Request:
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
# 二次封装request,将原生request作为drf-request对象的_request属性
self._request = request
self.parsers = parsers or ()
self.authenticators = authenticators or ()
self.negotiator = negotiator or self._default_negotiator()
self.parser_context = parser_context
self._data = Empty
self._files = Empty
self._full_data = Empty
self._content_type = Empty
self._stream = Empty # 以后使用request对象,就像使用之前的request是一模一样(因为重写了__getattr__方法,request.methed用法是一样的,不用request._request.methed,request.属性的时,自动触发__getattr__方法
def __getattr__(self, attr):
try:
# 放射,从原生request对象中取属性方法
return getattr(self._request, attr)
except AttributeError:
# 改进,不仅可以点取属性,还可以用[]的形式取属性,类.__dict__
return self.__getattribute__(attr) # request.data 不是属性,是@property修饰的一个方法
# 还有返回的一个字典,post请求不管使用什么编码(urldecode、formdata、json),传过来的数据,都在request.data,
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data # GET方发虽然重写了,还是request.GET,
@property
def query_params(self):
return self._request.GET # 视图类中
print(request.query_params)
'''
也是GET过来的数据,作者给改了个名,认为query_params是查询集,
更符合drf规范,本来get过来的数据就是查询集
'''
print(request.GET)
drf(初始drf,restfull规范 ,CBV、APIView、Request源码)的更多相关文章
- DRF cbv源码分析 restful规范10条 drf:APIView的源码 Request的源码 postman的安装和使用
CBV 执行流程 路由配置:url(r'^test/',views.Test.as_view()), --> 根据路由匹配,一旦成功,会执行后面函数(request) --> 本质就是执 ...
- APIView源码与Request源码分析
一.APIView源码分析 1.安装djangorestframework 2.使用 drf是基于cbv view的封装,所以必须写cbv ①第一步:写视图,必须写cbv 路由配置: from res ...
- Django day24 cbv和APIView的源码分析 和 resful的规范
一:cbv的源码分析 1.CBV和FBV的区别: - Class Base View CBV(基于类的视图) - Function Base View FBV(基于函数的视图) 2.as_vi ...
- Django框架之drf:5、反序列化器校验部分源码分析、断言、drf之请求与响应、视图组件介绍及两个视图基类、代码部分实战
Django框架之drf 目录 Django框架之drf 一.反序列化类校验部分源码解析 二.断言 三.drf之请求 1.Request能够解析的前端传入编码格式 2.Request类中的属性和方法 ...
- Flask快速入门day02(1、CBV使用及源码分析,2、模板用法,3、请求与响应的基本用法,4、session的使用及源码分析,5、闪现,6、请求扩展)
目录 Flask框架 一.CBV分析 1.CBV编写视图类方法 二.CBV源码分析 1.CBV源码问题 2.补充问题 3.总结 三.模板 1.py文件 2.html页面 四.请求与响应 1.reque ...
- FBV和CBV的区别(源码分析)
FBV和CBV源码分析 FBV直接调用user方法执行业务代码 CBV相当于在FBV上面封装了一层 from django.contrib import admin from django.urls ...
- 代码规范、GitHub提交源码的标准 答题人-杨宇杰
1.格式与命名规范1.1 缩进 使用Tab缩进,而不是空格键1.2 换行 每行120字符 if,for,while语句只有单句时,如果该句可能引起阅读混淆,需要用" {"和&quo ...
- JAVAEE 是什么,如何获取各种规范jar包及各种规范的jar包源码
1.什么是JAVA EE JAVA EE是由一系列规范组成的,规范是由JCP制定的,并且提供了参考实现.规范(Specification)是一系列接口,不包含具体实现 有以下常见的JAVA EE实现, ...
- 【DRF框架】restfull规范
零:核心思想: 1.面对资源编程 2.根据HTTP请求方式的不同对资源进行不同的操作 一.协议 API与用户的通信协议,总是使用HTTPs协议. 二.域名 应该尽量将API部署在专用域名之下. htt ...
- django:CBV模式,源码解析
非常好 DRF执行流程源码解析 https://www.cnblogs.com/suguangti/p/11120793.html https://www.cnblogs.com/haitaoli/p ...
随机推荐
- Lora 模块E22-400T22D(SX1268, 22dBm)
无线串口(UART)模块, 基于SEMTECH SX1268射频芯片, 具有多种传输方式, 工作在410.125至493.125MHz频段(默认 433.125MHz). LoRa扩频技术, TTL电 ...
- Python中文件读写操作
1 txt文件 1.1 写操作 import numpy as np def write(fileName,data): file=open(fileName,'w') row,col=data.sh ...
- ORA-39087: Directory Name Is Invalid
说明 有时我们在Oracle数据库服务器执行expdp/impdp过程中会碰到这个错误:ORA-39087: Directory Name Is Invalid,意思是我们指定的directory参数 ...
- Java网络编程之使用URL类
Lesson: Working with URLs 使用URLs 整理自Oracle官方文档. URL is the acronym for Uniform Resource Locator. URL ...
- Java并发编程实例--3.打断一个线程
一般来讲一个java程序如果运行着多个线程,那么只有在这些线程都运行完毕后才会终止. 但有时候,我们需要去结束某个线程或者取消某个任务.此时就用到了Java线程的打断机制,即interruption. ...
- 解密prompt系列24. RLHF新方案之训练策略:SLiC-HF & DPO & RRHF & RSO
去年我们梳理过OpenAI,Anthropic和DeepMind出品的经典RLHF论文.今年我们会针对经典RLHF算法存在的不稳定,成本高,效率低等问题讨论一些新的方案.不熟悉RLHF的同学建议先看这 ...
- Vue3学习(十九) - TreeSelect 树选择
写在前面 我知道自己现在的状态很不好,以为放个假能好好放松下心情,结果昨晚做梦还在工作,调试代码,和领导汇报工作. 天呐,明明是在放假,可大脑还在考虑工作的事,我的天那,这是怎么了? Vue页面参数传 ...
- 1.Go 的基本数据类型
Go 的基本数据类型
- DataGear 制作折柱图数据可视化图表
利用 DataGear 看板的 自定义图表选项 功能,可以很方便地制作折柱图(或者折线-饼图.柱状-饼图)数据可视化图表. 假设有如下CSV数据集,包括名称和两个指标值数据: 名称, 指标0, 指标 ...
- 【API Management】使用 APIM Inbound Policy 来修改Content‐Type Header的值
问题描述 在使用APIM提供API服务管理的场景中,遇见了客户端请求时候发送的请求Header中的Content-Type不满足后台服务器的要求,但是在客户端要求客户修改代码难度较高. 所以面对这样的 ...