rest_framework视图和组件
一、视图
1.基本视图
#基本视图
#抽取基类
from rest_framework.response import Response
from rest_framework.views import APIView
from app1.models import *
from app1.Myserializer import BookSerializer
from app1.Myserializer import PublishSerializer
class List():
def list(self,request,*args,**kwargs):
response = {'status':100,'msg':'查询成功'}
g = self.model
g_ser = self.model_ser(instance=g,many=True)
response['data'] = g_ser.data
return Response(response) class Create():
def create(self,request,*args,**kwargs):
response = {'status': 100, 'msg': '新增成功'}
try:
p_ser = self.model_ser(data=request.data)
if p_ser.is_valid():
p_ser.save()
response['data'] = p_ser.data
else:
response['msg'] = p_ser.errors
except Exception as e:
response['msg'] = str(e)
return Response(response) #图书查询,新增
class BooksView(List,Create,APIView):
model = Book.objects.all()
model_ser = BookSerializer
def get(self,request,*args,**kwargs):
return self.list(request,*args,**kwargs) def post(self,request,*args,**kwargs):
return self.create(request,*args,**kwargs) #出版社查询,新增
class PublishView(List,Create,APIView):
model = Publish.objects.all()
model_ser = PublishSerializer
def get(self,request,*args,**kwargs):
return self.list(request,*args,**kwargs) def post(self,request,*args,**kwargs):
return self.create(request,*args,**kwargs)
2.mixin类和generice类编写视图
from app1.models import *
from app1.Myserializer import BookSerializer
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
from rest_framework.generics import GenericAPIView
#ListModelMixin:获取所有 CreateModelMixin:新增 RetrieveModelMixin:获取单本 UpdateModelMixin:更新 DestroyModelMixin:删除
class BooksView(ListModelMixin,CreateModelMixin,GenericAPIView):
serializer_class = BookSerializer
queryset = Book.objects.all()
#获取所有图书
def get(self,request,*args,**kwargs):
return self.list(request,*args,**kwargs) #新增图书
def post(self,request,*args,**kwargs):
return self.create(request,*args,**kwargs) class BookView(RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView):
serializer_class = BookSerializer
queryset = Book.objects.all() #获取单本
def get(self,request,*args,**kwargs):
return self.retrieve(request,*args,**kwargs) #更新图书
def put(self, request, *args, **kwargs):
return self.update(request,*args,**kwargs) #删除图书
def delete(self,request,*args,**kwargs):
return self.destroy(request,*args,**kwargs)
3.使用generics 下ListCreateAPIView,RetrieveUpdateDestroyAPIView
from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView
#获取所有和新增图书
class BooksView(ListCreateAPIView):
serializer_class = BookSerializer
queryset = Book.objects.all() #查询单个图书,更新,删除
class BookView(RetrieveUpdateDestroyAPIView):
serializer_class = BookSerializer
queryset = Book.objects.all()
4.使用ModelViewSet,将两个视图类写成一个类,五种请求:get,get,post,delete
from app1.models import *
from app1.Myserializer import BookSerializer
from rest_framework.viewsets import ModelViewSet
class BooksView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer #路由层路由配置
url(r'^books/$', views.BooksView.as_view({'get':'list','post':'create'})),
url(r'^books/(?P<pk>\d+)$',\
views.BooksView.as_view({'get':'retrieve','put':'update','delete':'destroy'})),
5.ViewSetMixin的使用,重写了as_view方法
要用ViewSetMixin,路由跟之前写法不一样了
url(r'^test', views.Publish.as_view({'get':'aa'})), 视图类中
from rest_framework.viewsets import ViewSetMixin
class Publish(ViewSetMixin,APIView):
def aa(self,request):
return HttpResponse('aa')
二、认证组件
-什么是认证?是用来干什么的?
校验用户是否是我的登录用户 -drf源码中找,认证如何实现的
-APIView的dispach方法---》self.initial(request, *args, **kwargs)----》400行self.perform_authentication(request)---》APIView的perform_authentication(request)----》request.user(request是新的request)---->去Request类中找user,执行--->self._authenticate()(self是新的reqeust对象)---->Request类的_authenticate(self)方法
使用认证功能
'''
1.①写一个认证类MyAuthentication,继承BaseAuthentication
②类的内部重写authenticate方法
③在authenticate方法中写认证逻辑,认证通过,返回None,认证不通过,抛异常
④校验通过,也可以返回当前登录的用户和auth,这样操作,在视图类中,可以通过request.user,获取到当前登录的用户
⑤一旦返回了值,后续的认证类就不会再走了
''' '''
2.authentication_classes查找顺序(认证类的查找顺序):
①先在自己类当中找:authentication_classes=[MyAuthentication]
②如果自己当中没有配置,去去项目settings.py中去找
③如果项目setting中没有配置,去drf的setting中找
''' '''
3.最终在认证中的使用
局部使用:
-在视图类中配置:authentication_classes=[MyAuthentication]
全局使用:
-在setting.py中配置:
REST_FRAMEWORK={
'DEFAULT_AUTHENTICATION_CLASSES':['app1.MyAuth.MyAuthentication']
}
全局使用了局部禁用:
-在视图类中配置:authentication_classes=[]
''' from rest_framework.response import Response
from app1.models import *
from rest_framework.views import APIView
import uuid
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.authentication import BaseAuthentication class MyAuthentication(BaseAuthentication):
def authenticate(self,request):
#认证相关的东西
#校验请求是否携带正确的token
#取出token
token = request.GET.get('token')
#校验该次请求是否携带正确的token
ret = UserToken.objects.filter(token=token).first()
if ret:
#正常通过认证的用户
return ret.user,ret
else:
#没有登录或非法用户
raise AuthenticationFailed('您没有通过认证') class BooksView(APIView):
#某个视图类需要登陆后才能查看,只需要在视图类加入下面代码
authentication_classes=[MyAuthentication]
def get(self,request):
return Response('ok') class Login(APIView):
def post(self,request):
response={'status':100,'msg':None}
name = request.data.get('name')
pwd = request.data.get('pwd') #去数据库校验数据是否存在
user = User.objects.filter(name=name,pwd=pwd).first()
if user:
#正常用户登录成功 #返回唯一的随机字符串
token = uuid.uuid4() #生成随机的字符串存到数据库中,如果存在更新token,不存在新增一条
# 根据user去查询,如果查到数据,更新defaults中的数据,如果查不到,新增一条数据
ret = UserToken.objects.update_or_create(user=user,defaults={'token':token})
response['msg'] = '登录成功'
response['token'] = token
else:
response['status'] = 101
response['msg'] = '账号或密码错误'
return Response(response) #请求
#http://127.0.0.1:8000/books/?token=735061c3-733d-463d-8158-ccfa2e13f539
#token匹配成功就会得到图书信息,否则返回没有通过认证 #加了 authentication_classes=[MyAuthentication] 这句代码,直接访问http://127.0.0.1:8000/books/ 会返回没有通过认证
三、权限组件
'''
权限是什么?
比如只有超级用户可以访问books这个接口
使用:
①写一个权限类MyPermissions,继承BasePermission
②类的内部重写has_permission方法
③在has_permission方法内部写权限逻辑,通过返回True,失败返回False
'''
user表
class User(models.Model):
name=models.CharField(max_length=32)
pwd=models.CharField(max_length=32)
choice=((1,'超级用户'),(2,'普通用户'),(3,'穷逼用户'))
type = models.IntegerField(choices=choice,null=True) from rest_framework.permissions import BasePermission
class MyPermissions(BasePermission):
def has_permission(self, request, view):
#是否为超级用户
if request.user.type == 1:
#如何取type对应的文字 get_字段名_display()
user_type = request.user.get_type_display()
#超级用户校验通过返回True
return True
else:
#校验失败返回False
return False '''
最终的使用
局部使用:
-在视图类中配置:permission_classes=[MyPermissions]
全局使用:
-在settings.py中配置:
REST_FRAMEWORK={
'DEFAULT_PERMISSION_CLASSES':['app1.MyAuth.MyPermissions']
}
全局使用了局部禁用:
-在视图类中配置:permission_classes=[]
四、频率组件
'''
频率是什么?
-同一段时间内,只能访问多少次
'''
频率组件的使用:
①写一个频率类Mythrottling,继承SimpleRetaThrottle
②重写get_cache_key方法,方法返回什么,频率组件就以什么做限制(比如返回ip,就以ip做限制.返回user_id,就会以用户id做限制)
from rest_framework.throttling import SimpleRateThrottle
class MyThrottling(SimpleRateThrottle):
scope = 'xxx'
def get_cache_key(self, request, view):
return request.META.get('REMOTE_ADDR') #返回客户端ip地址 ③在setings.py中配置:
'DEFAULT_THROTTLE_CLASSES':{
'xxx:'3/m' #每分钟三次
} ④局部使用:
-在视图类中配置:throttle_classes=[MyThrottling]
全局使用:
-在settings.py中配置
REST_FRAMEWORK={
'DEFAULT_THROTTLE_CLASSES':['app1.MyAuth.MyThrottling']
}
全局使用了局部禁用:
-在视图类中配置:throttle_classes=[]
自定义频率控制类
'''
频率控制的逻辑
某个ip地址一分钟只能访问三次
{ip地址1:[第三次访问的时间,第二次访问的时间,第一次访问的时间],ip地址2:[]}
(1)取出访问者ip
(2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
(3)循环判断当前ip的时间列表,有值,并且当前时间减去列表的最后一个时间大于60s,把列表中最后一个数用pop去掉,这样列表中只有60s以内的访问时间,
(4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
(5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
'''
from rest_framework.throttling import BaseThrottle
class MyThrottling(BaseThrottle):
#访问者ip字典
VISIT_RECORD = {}
def __init__(self):
#访问者ip对应的时间列表
self.history=None
def allow_request(self, request, view):
#(1)取出访问者ip
ip = request.META.get('REMOTE_ADDR')
#获取当前时间
import time
ctime = time.time()
#(2)判断当前ip不在访问字典里,添加进去,并且直接返回True, 表示第一次访问,在字典里,继续往下走
if ip not in self.VISIT_RECORD:
self.VISIT_RECORD[ip]=[ctime,]
return True
#获取当前访问者的时间列表self.history
self.history = self.VISIT_RECORD.get(ip)
#(3)循环判断当前ip的时间列表,有值,并且当前时间减去列表的最后一个时间大于60s,把列表中最后一个数据用pop去掉,这样列表中只有60s以内的访问时间
while self.history and ctime-self.history[-1] > 60:
self.history.pop()
#(4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
#(5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败 if len(self.history) < 3:
self.history.insert(0,ctime)
return True
else:
return False #还要等待的时间
def wait(self):
import time
ctime = time.time()
return 60 - (ctime-self.history[-1])
rest_framework视图和组件的更多相关文章
- Django的rest_framework的分页组件源码分析
前言: 分页大家应该都很清楚,今天我来给大家做一下Django的rest_framework的分页组件的分析:我的讲解的思路是这样的,分别使用APIview的视图类和基于ModelViewSet的视图 ...
- Django的rest_framework的权限组件和频率组件源码分析
前言: Django的rest_framework一共有三大组件,分别为认证组件:perform_authentication,权限组件:check_permissions,频率组件:check_th ...
- Django之REST_framework 框架基本组件使用
快速实例 快速实例: 点击查看官方文档 阅读推荐:点击查看 序列化 创建一个序列化类 简单使用 开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如j ...
- rest_framework之序列化组件
什么是rest_framework序列化? 在写前后端不分离的项目时: 我们有form组件帮我们去做数据校验 我们有模板语法,从数据库取出的queryset对象不需要人为去转格式 当我们写前后端分离项 ...
- 关于Android界面编程与视图(View)组件
UI组件--------------->android.widget.* View组件------------->android.view.* 视图(View)组件 所有UI组件都是建立在 ...
- rest_framework解析器组件源码流程
rest_framework解析器组件源码流程 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数 ...
- Android零基础入门第54节:视图切换组件ViewSwitcher
原文:Android零基础入门第54节:视图切换组件ViewSwitcher 前面三期学习了ProgressBar系列组件,那本期开始一起来学习ViewAnimator组件. 一.ViewAnimat ...
- DRF(3) - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件
一.序列化组件 基于上篇随笔的表结构,通过序列化组件的ModelSerializer设计如下三个接口: GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} PU ...
- DRF - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件
一.序列化组件 基于上篇随笔的表结构 , 通过序列化组件的ModelSerializer设计如下三个接口 : GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} ...
随机推荐
- web.py框架之i18n支持
问题: 在web.py的模板文件中, 如何得到i18n的支持? Solution: 项目目录结构: proj/ |- code.py |- i18n/ |- messages.po |- en_US/ ...
- H - Expedition 优先队列 贪心
来源poj2431 A group of cows grabbed a truck and ventured on an expedition deep into the jungle. Being ...
- python接口自动化测试(c测试环境的准备)
接口测试的方式有很多,比如可以用工具(jmeter,postman)之类,也可以自己写代码进行接口测试,工具的使用相对来说都比较简单,重点是要搞清楚项目接口的协议是什么,然后有针对性的进行选择,甚至当 ...
- 【C++ 模板迭代器实例/半素数】
题目:判断一个数是不是两个素数的乘积,是输出YES,不是输出NO.数据范围为2-1000000. 为了解决这个问题,我们继续使用STL——vector & set,分别用来存储素数和半素数.为 ...
- layer[申明:来源于网络]
layer[申明:来源于网络] 地址:http://layer.layui.com/
- shop_z 一套非常适合二次开发的php后台管理系统
QQ群:247823727 如果你需要定制某些功能开联系群主,价格实惠,后期交接完善,有上手培训 shop_z基础thinkphp5 php7上开发运行,速度杠杠的 地址:https://gitee ...
- 单片机小白应该如何学习stm32的一些实践心得!
嵌入式搬砖道路上的大三狗一枚,撑死算个初学者吧.才学有限,下面仅仅是本人对STM32学习的一点心得与建议,希望对题主有帮助吧. 心得:本人当初学习STM32的时候有一些跟风的因素,自以为学的芯片越多就 ...
- apache tomcat (catalina)查版本(solaris/unix)
先进到tomcat的bin目录下(cd /tomcat目录/bin),在执行./version.sh https://blog.csdn.net/vv___/article/details/78653 ...
- 【转载】word2vec原理推导与代码分析
本文的理论部分大量参考<word2vec中的数学原理详解>,按照我这种初学者方便理解的顺序重新编排.重新叙述.题图来自siegfang的博客.我提出的Java方案基于kojisekig,我 ...
- python练习题-day10
1.继续整理函数相关知识点,写博客. 2.写函数,接收n个数字,求这些参数数字的和.(动态传参) def fun(*args): sum=0 for i in args: sum+=i return ...