Drf06 /drf总结
Drf06 /drf总结
1. restful规范
restful是一套规则,是程序间进行数据传输的一种约定
1.建议用https代替http,为了保证数据的安全
2.在url中添加api标识,这样看到url就知道是一个api,建议放在域名后面,这样不会存在跨域问题
3.在接口中体现版本信息,方便于版本的迭代,
4.restful也称面向资源编程,视网上的一切都是资源,所以一般资源都用名词
5.如果要添加一些筛选条件,可以写在url中
6.根据method不同做不同的操作
7.返回给用户状态码
8.对不同请求返回不同的数据
9.如果有异常返回错误信息
10.对于下一个请求要返回一个接口
2. drf组件认证的实现过程?
1.当用户请求过来时,执行dispatch,通过initialize_request方法,
2.找到认证的所有类并实例化成对象列表,然后将对象列表封装到新的request对象中。
3.执行下面的initial方法,经过认证的request.user方法
4.在内部会循环认证的对象列表,并执行每个对象的authenticate方法,该方法用于认证,返回值有三种,①抛出异常②返回None③返回一个元组
5.返回元组的两个值分别赋值给request.user和request.auth
3. drf组件中权限的实现过程?
1.当用户请求过来时,先执行dispatch方法,通过initial方法执行check_permissions方法
2.找到权限的所有类并实例化成对象列表
3.循环该实例化对象列表,执行每个对象的has_permission方法
4.返回True和False进行权限的认证,可定制错误信息
4. drf组件中节流的实现方式?
- 实现原理
来访问时:
1.获取当前时间 100121280
2.100121280-60 = 100121220,小于100121220所有记录删除
3.判断1分钟以内已经访问多少次了? 4
4.无法访问
停一会
来访问时:
1.获取当前时间 100121340
2.100121340-60 = 100121280,小于100121280所有记录删除
3.判断1分钟以内已经访问多少次了? 0
4.可以访问
- 具体流程
请求来时会执行allow_follow方法,
会用self.key获取请求用户的ip,再用self.history根据用户的ip获取其访问的记录,
获取当前的时间,用当前的时间减去设定的时间段,
循环该用户访问的记录,将不在该时间段的记录pop掉,
通过len判定该时间段已经访问了多少次,超过限定次数会返回false
匿名用户是通过ip进行访问限制,登录用户通过用户的id进行访问限制
5. 什么是jwt?优势?
一般用于做用户认证(登录)使用的技术。
jwt的实现原理:
- 用户登录成功之后,会给前端返回一段token。
- token是由.分割的三段组成。
- 第一段:类型和算法信息 -- header
- 第二段:用户信息+超时时间 -- payload
- 第三段:hs256(前两段拼接)加密 + base64url -- sign
- 以后前端再次发来信息时
- 超时验证
- token合法性校验
优势:
- token只在前端保存,后端只负责校验。
- 内部集成了超时时间,后端可以根据时间进行校验是否超时。
- 由于内部存在hash256加密,所以用户不可以修改token,只要一修改就认证失败。
6.drf框架
drf是一个基于django开发的组件,本质是一个django的app。
drf可以为我们快速开发出一个遵循restful规范的程序。
1.drf为我们提供了一大堆视图,ListAPIView,RetrieveAPIView,DestroyAPIView,UpdateAPIView,CreateAPIView,可以帮我们快速的进行增删改查,但是只能完成最基本的对表格的增删改查,想要更多的功能可以重写视图的方法
2.版本的处理
3.认证
4.权限
5.截流(频率限制)
6.视图过后进入解析器,有request.data,reqeust.querysetparams.get('pk')
7.序列化,可以对用户数据进行校验以及序列化
8.筛选器
9.分页
10.渲染
7.写视图的方法
第一种:原始APIView
url(r'^login/$',account.LoginView.as_view()),
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework_jwt.settings import api_settings
from rest_framework.throttling import AnonRateThrottle
from api import models class LoginView(APIView):
authentication_classes = []
def post(self,request,*args,**kwargs):
# 1.根据用户名和密码检测用户是否可以登录
user = models.UserInfo.objects.filter(username=request.data.get('username'),password=request.data.get('password')).first()
if not user:
return Response({'code':10001,'error':'用户名或密码错误'}) # 2. 根据user对象生成payload(中间值的数据)
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
payload = jwt_payload_handler(user) # 3. 构造前面数据,base64加密;中间数据base64加密;前两段拼接然后做hs256加密(加盐),再做base64加密。生成token
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
token = jwt_encode_handler(payload)
return Response({'code': 10000, 'data': token})
第二种:ListApiView等
url(r'^article/$',article.ArticleView.as_view()),
url(r'^article/(?P<pk>\d+)/$',article.ArticleDetailView.as_view()),
from rest_framework.throttling import AnonRateThrottle
from rest_framework.response import Response
from rest_framework.generics import ListAPIView,RetrieveAPIView
from api import models
from api.serializer.article import ArticleSerializer,ArticleDetailSerializer class ArticleView(ListAPIView):
authentication_classes = []
# throttle_classes = [AnonRateThrottle,] queryset = models.Article.objects.all()
serializer_class = ArticleSerializer class ArticleDetailView(RetrieveAPIView):
authentication_classes = []
queryset = models.Article.objects.all()
serializer_class = ArticleDetailSerializer
第三种:
url(r'^article/$',article.ArticleView.as_view({"get":'list','post':'create'})),
url(r'^article/(?P<pk>\d+)/$',article.ArticleView.as_view({'get':'retrieve','put':'update','patch':'partial_update','delete':'destroy'}))
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin
from api.serializer.article import ArticleSerializer,ArticleDetailSerializer class ArticleView(GenericViewSet,ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin):
authentication_classes = []
throttle_classes = [AnonRateThrottle,] queryset = models.Article.objects.all()
serializer_class = None def get_serializer_class(self):
pk = self.kwargs.get('pk')
if pk:
return ArticleDetailSerializer
return ArticleSerializer
drf 相关知识点梳理
装饰器
def outer(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner @outer
def index(a1):
pass index()
def outer(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner def index(a1):
pass index = outer(index) index()
django中可以免除csrftoken认证
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import HttpResponse @csrf_exempt
def index(request):
return HttpResponse('...') # index = csrf_exempt(index) urlpatterns = [
url(r'^index/$',index),
]
urlpatterns = [
url(r'^login/$',account.LoginView.as_view()),
] class APIView(View):
@classmethod
def as_view(cls, **initkwargs):
view = super().as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs # Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)
面向对象中基于继承+异常处理来做的约束
class BaseVersioning:
def determine_version(self, request, *args, **kwargs):
raise NotImplementedError("must be implemented") class URLPathVersioning(BaseVersioning):
def determine_version(self, request, *args, **kwargs):
version = kwargs.get(self.version_param, self.default_version)
if version is None:
version = self.default_version if not self.is_allowed_version(version):
raise exceptions.NotFound(self.invalid_version_message)
return version面向对象封装
class Foo(object):
def __init__(self,name,age):
self.name = name
self.age = age obj = Foo('汪洋',18)class APIView(View):
def dispatch(self, request, *args, **kwargs): self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
... def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request) return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(), # [MyAuthentication(),]
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)面向对象继承
class View(object):
pass class APIView(View):
def dispatch(self):
method = getattr(self,'get')
method() class GenericAPIView(APIView):
serilizer_class = None def get_seriliser_class(self):
return self.serilizer_class class ListModelMixin(object):
def get(self):
ser_class = self.get_seriliser_class()
print(ser_class) class ListAPIView(ListModelMixin,GenericAPIView):
pass class UserInfoView(ListAPIView):
pass view = UserInfoView()
view.dispatch()class View(object):
pass class APIView(View):
def dispatch(self):
method = getattr(self,'get')
method() class GenericAPIView(APIView):
serilizer_class = None def get_seriliser_class(self):
return self.serilizer_class class ListModelMixin(object):
def get(self):
ser_class = self.get_seriliser_class()
print(ser_class) class ListAPIView(ListModelMixin,GenericAPIView):
pass class UserInfoView(ListAPIView):
serilizer_class = "汪洋" view = UserInfoView()
view.dispatch()class View(object):
pass class APIView(View):
def dispatch(self):
method = getattr(self,'get')
method() class GenericAPIView(APIView):
serilizer_class = None def get_seriliser_class(self):
return self.serilizer_class class ListModelMixin(object):
def get(self):
ser_class = self.get_seriliser_class()
print(ser_class) class ListAPIView(ListModelMixin,GenericAPIView):
pass class UserInfoView(ListAPIView): def get_seriliser_class(self):
return "咩咩" view = UserInfoView()
view.dispatch()反射
class View(object):
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
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)发送ajax请求
$.ajax({
url:'地址',
type:'GET',
data:{...},
success:function(arg){
console.log(arg);
}
})浏览器具有 "同源策略的限制",导致
发送ajax请求
+跨域
存在无法获取数据。- 简单请求,发送一次请求。
- 复杂请求,先options请求做预检,然后再发送真正请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>常鑫的网站</h1>
<p>
<input type="button" value="点我" onclick="sendMsg()">
</p>
<p>
<input type="button" value="点他" onclick="sendRemoteMsg()">
</p> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script>
function sendMsg() {
$.ajax({
url:'/msg/',
type:'GET',
success:function (arg) {
console.log(arg);
}
})
}
function sendRemoteMsg() {
$.ajax({
url:'http://127.0.0.1:8002/json/',
type:'GET',
success:function (arg) {
console.log(arg);
}
}) }
</script>
</body>
</html>如何解决ajax+跨域?
CORS,跨站资源共享,本质:设置响应头。
常见的Http请求方法
get
post
put
patch
delete
optionshttp请求中Content-type请起头
情况一:
content-type:x-www-form-urlencode
name=alex&age=19&xx=10 request.POST和request.body中均有值。 情况二:
content-type:application/json
{"name":"ALex","Age":19} request.POST没值
request.body有值。django中F查询
django中获取空Queryset
models.User.object.all().none()
基于django的fbv和cbv都能实现遵循restful规范的接口
def user(request):
if request.metho == 'GET':
pass class UserView(View):
def get()... def post...基于django rest framework框架实现restful api的开发。
- 免除csrf认证
- 视图(APIView、ListAPIView、ListModelMinx)
- 版本
- 认证
- 权限
- 节流
- 解析器
- 筛选器
- 分页
- 序列化
- 渲染器简述drf中认证流程?
简述drf中节流的实现原理以及过程?匿名用户/非匿名用户 如何实现频率限制?
GenericAPIView视图类的作用?
他提供了一些规则,例如: class GenericAPIView(APIView):
serializer_class = None
queryset = None
lookup_field = 'pk' filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS def get_queryset(self):
return self.queryset def get_serializer_class(self):
return self.serializer_class def filter_queryset(self, queryset):
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset @property
def paginator(self):
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator 他相当于提供了一些规则,建议子类中使用固定的方式获取数据,例如:
class ArticleView(GenericAPIView):
queryset = models.User.objects.all() def get(self,request,*args,**kwargs):
query = self.get_queryset() 我们可以自己继承GenericAPIView来实现具体操作,但是一般不会,因为更加麻烦。
而GenericAPIView主要是提供给drf内部的 ListAPIView、Create....
class ListModelMixin:
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data) class ListAPIView(mixins.ListModelMixin,GenericAPIView):
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) class MyView(ListAPIView):
queryset = xxxx
ser...总结:GenericAPIView主要为drf内部帮助我们提供增删改查的类LIstAPIView、CreateAPIView、UpdateAPIView、提供了执行流程和功能,我们在使用drf内置类做CURD时,就可以通过自定义 静态字段(类变量)或重写方法(get_queryset、get_serializer_class)来进行更高级的定制。
jwt以及其优势。
序列化时many=True和many=False的区别?
many=True 序列化多个数据
many=False 序列化单个数据应用DRF中的功能进行项目开发
*****
解析器:request.query_parmas/request.data
视图
序列化
渲染器:Response ****
request对象封装
版本处理
分页处理
***
认证
权限
节流- 基于APIView实现呼啦圈
- 继承ListAPIView+ GenericViewSet,ListModelMixin实现呼啦圈
jwt和传统的token的区别?
# 补充
传统的token会放在缓冲中,redis缓冲中,实际上不会放在数据库
Drf06 /drf总结的更多相关文章
- DRF如何序列化外键的字段
我觉得在有些应用场景下,这个操作是有用的,因为可以减少一个AJAX的请求,以增加性能. 当然,是二次请求,还是一次传输.这即要考虑用户体验,还要兼顾服务器性能. 一切是有条件的平衡吧.就算是一次传输, ...
- DRF限制访问频次
官方文档:https://www.django-rest-framework.org/api-guide/throttling/ 1.什么场景下需要限制访问频次呢? 1)防爬虫:爬虫可能会在短时间内大 ...
- DRF缓存
对于现在的动态网站来讲,所有的界面展示都是通过客户端请求服务端,服务端再去请求数据库,然后将请求到的数据渲染后返回给客户端.用户每次访问页面都需要去请求数据库,如果同时有多个人访问的话,对于我们的数据 ...
- drf相关问题
drf自定义用户认证: 登录默认 使用django的ModelBackend,对用户名和密码进行验证.但我们平时登录网站时除了用户名也可以用邮箱或手机进行登录,这就需要我们自己扩展backend 一. ...
- DRF 缓存解决方案 drf-extensions / redis
drf-extensions 概述 drf-extensions组件内部提供了 DRF 的本地内存方式的缓存方式 本地内存方式缓存在项目重启后则会消失 官方点击 这里 安装 pip3 install ...
- DRF 商城项目 - 用户( 登录, 注册,登出,个人中心 ) 逻辑梳理
用户登录 自定义用户登录字段处理 用户的登录时通过 手机号也可以进行登录 需要重写登录验证逻辑 from django.contrib.auth.backends import ModelBacken ...
- luffy项目后台drf搭建(1)
一 进入虚拟环境 打开crm,输入命令 workon luffy 虚拟环境使用文档 二 安装基本类库 pip install django pip install PymySQL pip instal ...
- DRF项目创建流程(1)
一 web应用模式 前后端不分离 前后端分离 二 RESTFUL API规范 REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态 ...
- DRF初识与序列化
一.Django的序列化方法 1.为什么要用序列化组件 做前后端分离的项目,我们前后端数据交互一般都选择JSON,JSON是一个轻量级的数据交互格式.那么我们给前端数据的时候都要转成json格式,那就 ...
随机推荐
- firda安装和使用
frida是一个轻量级别的hook框架. frida由两部分组成:一部分是运行在系统上的交互工具frida CLI,另一部分是运行在目标机器上的代码注入工具frida-server. 推荐使用pyth ...
- 对于Python的GIL锁理解
GIL是什么 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可 ...
- 自己动手实现深度学习框架-8 RNN文本分类和文本生成模型
代码仓库: https://github.com/brandonlyg/cute-dl 目标 上阶段cute-dl已经可以构建基础的RNN模型.但对文本相模型的支持不够友好, 这个阶段 ...
- CISCN 2019-ikun
0x01 进去网址,页面如下: 刚开始有个登陆和注册的按钮,上图是我已经注册后登陆成功后的页面,我们发现在图的左下角给了一个关键的提示,购买LV6,通过寻找我们发现页面数很多,大概500页,一个一个找 ...
- Python爬虫小白入门(一)入门介绍
一.前言 你是不是在为想收集数据而不知道如何收集而着急? 你是不是在为想学习爬虫而找不到一个专门为小白写的教程而烦恼? Bingo! 你没有看错,这就是专门面向小白学习爬虫而写的!我会采用实例的方式, ...
- CentOS7.5搭建spark2.3.1集群
一 下载安装包 1 官方下载 官方下载地址:http://spark.apache.org/downloads.html 2 安装前提 Java8 安装成功 zookeeper 安 ...
- Linux下常用命令(持续更新)
l: 列举目录下的所有文件 ll: 显示详细属性 pwd: 查看当前所在完整路径 cd: 变更文件夹(变更到根目录:cd + /:变更到上级目录:cd + ..) sudo: 允许利用超级用户权限执行 ...
- Windows程序设计(2) -API-01 初识
Windows 程序原理 一,CPU的保护模式和windows操作系统 [x] windows 是多任务实现 [x] 虚拟内存和 各个进程的地址空间安排:2G系统空间,2G用户空间,2G用户空间是各个 ...
- Appium 概括与环境安装
Appium 是什么, 有什么用 Appium 用途和特点 appium 是一个移动 app 自动化工具 手机APP自动化有什么用? 自动化完成一些重要性的任务 比如微信客服机器人 爬虫 就是通过自动 ...
- Redis安装过程jemalloc/jemalloc.h报错
问题: [root@localhost redis-3.0.0]# make cd src && make all make[1]: Entering directory `/data ...