django rest_framework 框架的使用
django 的中间件 csrf
Require a present and correct csrfmiddlewaretoken for POST requests that have a CSRF cookie, and set an outgoing CSRF cookie.
This middleware should be used in conjunction with the {% csrf_token %}
template tag.
django 的中间件是基于 post 的请求,当post 请求到来的时候 在csrftoken 中间件中执行 process_view 验证 token的正确性,如果验证失败,则返回forbidden 提示给用户。
我们可以让中间件不起作用,首先第一种方法是在配置文件中的settings中注释掉cscftoken的中间件,这样其实存在安全隐患
其次我们可以在我们不需要验证csrftoken的视图view中加装饰器来使我们的视图函数免予csrftoken的校验,使用如下:
from django.shortcuts import render, HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt, csrf_protect # csrf_token 单独示例
from django.utils.decorators import method_decorator
# 基于函数的使用
@csrf_exempt
def index(request):
# what you want you view do in this
return HttpResponse("index")
# 基于类的方式 2-1
@method_decorator(csrf_exempt, name="dispatch")
class StudentView(View):
#方式 2-1
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
# do something before diaspatch
ret = super(StudentView, self).dispatch(request, *args, **kwargs)
#do somethig after dispatch
return ret
def get(self, request, *args, **kwargs):
return HttpResponse("GET")
def post(self, request, *args, **kwargs):
return HttpResponse("POST")
django 的CBV模式
django 中cbv模式中,已类来接受一个请求的到来,通过类继承 view 类
通过父类的dispatch 方法通过反射 进行请求方法的分发。我们也可以在继承父类的dispatch 方法 来自定制自己的一些操作,rest-framework 也是基于这个实现的,因此我们先看看下他的源码部分:
首先是url中的配置:
urlpatterns = [
re_path('^student/$', views.StudentView.as_view()),
re_path('^dog/$', views.DogView.as_view()),
]
当请求到来的时候,执行as_view() 方法让我们来看下 as_view()做了啥:
def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
.......
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs) # 看这里执行了View的dispatch 方法
view.view_class = cls
view.view_initkwargs = initkwargs
# take name and docstring from class
update_wrapper(view, cls, updated=())
# and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view
再来看看 view类的dispatch 方法:注意可定制的操作前面已经给出
def dispatch(self, request, *args, **kwargs):
# 这里的self. http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
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
return handler(request, *args, **kwargs)
rest_framework 的解读
首先 rest_framework 是为了遵循RESTful 规范而诞生的框架;
那我们首先需要知道什么是RESTful 规范
REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)
接下来让我们了解下他的API设计规范
1、在url接口中推荐使用Https协议,让网络接口更加安全(Https是Http的安全版,即HTTP下加入 SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL(安全套接层协议))
2、url中可以体现这是个API接口 域名规范
https://api.example.com 尽量将API部署在专用域名(会存在跨域问题)
https://example.org/api/ API很简单
- 3、url中还可以体现版本号,不同的版本可以有不同的接口,使其更加简洁,清晰
请求头跨域时, 引发发送多次请求
- 4、restful 提倡面向资源编程,所以在url接口中尽量要使用名词,不要使用动词
- 5、此外url中还可以添加条件去筛选匹配
过滤,通过在url上传参的形式传递搜索条件
https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
- 6、可以根据Http不同的method,进行不同的资源操作(5种方法:GET / POST / PUT / DELETE
/ PATCH)
GET :从服务器取出资源(一项或多项)
POST :在服务器新建一个资源
PUT :在服务器更新资源(客户端提供改变后的完整资源)
PATCH :在服务器更新资源(客户端提供改变的属性)
DELETE :从服务器删除资源
- 7、响应式应该包含状态码
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
- 8、应该有返回值,而且格式为统一的json格式
- 9、应该返回错误信息
- 10、返回结果中要提供帮助链接,即API最好做到Hypermedia
django的 rest_framework 组件的使用
1.首先我们的视图需要时候基于cbv的模式,我们的类需要继承rest_framework的view的 APIView 父类
如下:
class DogView(APIView):
def get(self, request, *args, **kwargs):
return HttpResponse("GET")
def post(self, request, *args, **kwargs):
return HttpResponse("POST")
接下来让我们研究下APIView的dispath 方法:
def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
# 对原生的request 加工(丰富)
""""
Request(
request,parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context)
原生的request = request._request
"""
# 首先是对原生的request进行了加个处理
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
我们来看下 self.initialize_request 这个方法实现方法
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request)
# self.get_authenticators() seteings配置的一个列表
# authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
# 对原生的request第二次加工
return Request(
request,
# 封装了解析器类
parsers=self.get_parsers(),
# 封装了用户用户认证的类
authenticators=self.get_authenticators(),
# url后缀名的显示方式 ex--> .json
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
1.首先是用户认证 的解析
在讨论源码之前我先rest_framework配置放在这里(后面需要修改的会加上去):
# 可以看这里
from rest_framework import settings
# List of settings that may be in string import notation.
IMPORT_STRINGS = (
'DEFAULT_RENDERER_CLASSES',
'DEFAULT_PARSER_CLASSES',
'DEFAULT_AUTHENTICATION_CLASSES',
'DEFAULT_PERMISSION_CLASSES',
'DEFAULT_THROTTLE_CLASSES',
'DEFAULT_CONTENT_NEGOTIATION_CLASS',
'DEFAULT_METADATA_CLASS',
'DEFAULT_VERSIONING_CLASS',
'DEFAULT_PAGINATION_CLASS',
'DEFAULT_FILTER_BACKENDS',
'DEFAULT_SCHEMA_CLASS',
'EXCEPTION_HANDLER',
'TEST_REQUEST_RENDERER_CLASSES',
'UNAUTHENTICATED_USER',
'UNAUTHENTICATED_TOKEN',
'VIEW_NAME_FUNCTION',
'VIEW_DESCRIPTION_FUNCTION'
)
封住完request之后接下来我们看看后面的源码
# 进行一系列的认证
#初始化进入验证,下面来看看initial 这个函数做了啥
self.initial(request, *args, **kwargs)
#--------------------------------------------------
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs)
.......
## 版本的控制的
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
# 认证
self.perform_authentication(request)
# 权限验证
self.check_permissions(request)
# 访问频率
self.check_throttles(request)
接下来讨论 认证方法
self.perform_authentication(request)源码:
View 类
def perform_authentication(self, request):
"""
Perform authentication on the incoming request.
Note that if you override this and simply 'pass', then authentication
will instead be performed lazily, the first time either
`request.user` or `request.auth` is accessed.
"""
request.user
Request 类
def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
# 遍历 setting defaults 的列表 的
"""
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
"""
# 执行每个self.authenticators类中的认证类方法:
for authenticator in self.authenticators:
try:
# 返回值有三种
"""
1.返回user 与 token 对象(认证成功)
2.返回None(不做处理,交个下一个)
3.抛出认证异常(认证失败)
"""
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
self._not_authenticated()
raise
if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return
self._not_authenticated()
认证类的写法:
# Lower 写法
class MyBasicAuthentication(object):
def authenticate(self, request):
token = request._request.GET.get("token")
if token:
return ("alex",None)
raise exceptions.AuthenticationFailed("failed")
def authenticate_header(self, val):
pass
"""我们可以继承他的类"""
# 基于用户token的认证
from rest_framework.authentication import BasicAuthentication
默认的几种用户认证类 自己写的可以继承BasicAuthentication
1.一中是自己定义类然后在view视图中这要表达:
authentication_classes=[ yourauthclass, ]
2.或者全局配置
REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":[.......]
}
接下来是用户权限的控制 这个比较简单直接上rest的自带的几个权限验证的源码类自己研究:
from rest_framework.permissions import BasePermission
class BasePermission(object):
"""
A base class from which all permission classes should inherit.
"""
def has_permission(self, request, view):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True
# 这个力度更加细致对于每个用户的管理,后面会将
def has_object_permission(self, request, view, obj):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True
django rest_framework 框架的使用的更多相关文章
- Python之Django rest_Framework框架源码分析
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_fram ...
- django rest_framework 框架的使用02
rest_framework 访问频率的限制(节流) 对于用户访问频率的显示,rest_framework 也有自己的类进行约束 先来一个自己的基于它的类的节流类的限制 class VisitCont ...
- django rest_framework 框架的使用03
rest_framework的 数据解析器 首先需要知道前端发给后端的数据格式头有哪些: media_type = 'application/json' media_type = 'applicati ...
- Django rest_framework 实用技巧
前言: 最近工作中需要用到Django rest_framework框架做API, 边学边写,记录了一些实际工作中需要用到的功能,不是很全也不系统,以后需要什么功能可以在这查询. 后续还会更新其它的用 ...
- Python之Django rest_Framework(2)
实例化: v1 = ["view.xxx.path.Role","view.xxx.path.Group",] 可以循环,循环出来的每一个不能实例化 如果把v1 ...
- python之Django rest_framework总结
一.rest api a.api就是接口 如: - http://www.oldboyedu.com/get_user/ - http://www. ...
- rest_framework框架下的Django声明和生命周期
rest_framework框架下的Django声明和生命周期 Django声明周期(request) 客户端发起请求 请求经过wsgi wsgi: 是一个协议----web服务网关接口,即在web服 ...
- Python之Django rest_Framework(3)
补充: 为什么要前后端分离: a.因为前端它有自己框架,这样它的效率就非常高 b.不做前后端分离,公司如果既有客户端,又有app这种情况下你就的写两遍 django rest ...
- rest_framework框架
rest_framework框架的认识 它是基于Django的,帮助我们快速开发符合RESTful规范的接口框架. 一 路由 可以通过路由as_view()传参 根据请求方式的不同执行对应不同的方法 ...
随机推荐
- [原][osg][osgearth]我眼中的osgearth
看了一下,OE生成的可执行文件 除了osg库和第三方库 OE生产最多的dll就是 osgdb_osgearth_XXXX.dll了 这些都是为了通过osgDB机制加载earth的数据用的. 所以,我觉 ...
- lua劈分字符串方法及实例
由于工作项目需要,最近需要用lua来写一些脚本.然而lua并不想java那样有很多的好用的api,很多方法得我们自己来编写和封装,就比如今天碰到的劈分字符串,查找资料后只能自己写了一个. 代码如下 - ...
- 【MySQL】经典数据库SQL语句编写练习题——SQL语句扫盲
[MySQL]数据库原理复习——SQL语言 对基本的SQL语句编写的练习题,其中的题目的答案可能会有多种书写方式. 1.题目1 1.1 关系模式 学生student:SNO:学号,SNAME:姓名,A ...
- orm框架的使用
Install npm install orm Node.js Version Support Supported: 0.12 - 6.0 + Tests are run on Travis CI I ...
- reg文件中文乱码
用reg文件方式修改注册表很方便,但是如果字段中有中文的话,执行reg文件后,注册表中的中文出现乱码. 解决办法:将文件保存文Unicode编码方式即可.(保存文UTF8编码也是不行的) 附一个添加\ ...
- SublimeText实用快捷键
Markdown Ctrl+Alt+O: Preview Markup in Browser Ctrl+Alt+X: Export Markup as HTML Ctrl+Alt+C: Copy Ma ...
- C++设计模式之享元模式
概述 想想我们编辑文档用的wps,文档里文字很多都是重复的,我们不可能为每一个出现的汉字都创建独立的空间,这样代价太大,最好的办法就是共享其中相同的部分,使得需要创建的对象降到最小,这个就是享元模式的 ...
- Struts2基本使用(一)--在项目中引入Struts2
Struts2基本使用 在MVC开发模式中,Struts2充当控制器(Controller)的角色.其主要功能就是处理用户请求,生成响应,是连接视图层(View)和模型层(Model)的桥梁.在处理用 ...
- php中require_once与include_once的区别
首先include_once仅包含文件一次,如果没有文件,会发出警告,并继续执行. 而require_once也是仅包含文件一次,但是如果程序中没有找到文件,则程序会中止执行.
- 20155236 2016-2017-2 《Java程序设计》第六周学习总结
20155236 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 InputStream与OutputStream 从应用程序角度来看,如果要将数据从来源取出 ...