Django之restframework2视图三部曲

视图三部曲

下面我来来看restframework是如何将冗余的代码一步步的进行封装.

这里主要用到的是多继承

第一步mixin类编写视图

1AuthorModelSerializer: 2 3class AuthorModelSerializer(serializers.ModelSerializer): 4 class Meta: 5 model=models.Author 6 fields='__all__' 7 8from rest_framework import mixins,generics 9class Authors(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView): 10 queryset = models.Author.objects.all() 11 serializer_class = AuthorModelSerializer 12 13 def get(self,request,*args,**kwargs): 14 return self.list(request,*args,**kwargs) 15 16 def post(self,request,*args,**kwargs): 17 return self.create(request,*args,**kwargs) 18 19class AuthorsDetailView(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,generics.GenericAPIView): 20 queryset = models.Author.objects.all() 21 serializer_class = AuthorModelSerializer 22 def get(self,request,*args,**kwargs): 23 return self.retrieve(request,*args,**kwargs) 24 25 def put(self,request,*args,**kwargs): 26 return self.update(request,*args,**kwargs) 27 28 def delete(self,request,*args,**kwargs): 29 return self.delete(request,*args,**kwargs)

第二部使用通用的基于类的视图

1from rest_framework import generics 2 3class Authors(generics.ListCreateAPIView): 4 queryset = models.Author.objects.all() 5 serializer_class = AuthorModelSerializer 6 7 8class AuthorsDetailView(generics.RetrieveUpdateDestroyAPIView): 9 queryset = models.Author.objects.all() 10 serializer_class = AuthorModelSerialize 11 12 13# class ListCreateAPIView(mixins.ListModelMixin, 14# mixins.CreateModelMixin, 15# GenericAPIView): 16# class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin, 17# mixins.UpdateModelMixin, 18# mixins.DestroyModelMixin, 19# GenericAPIView):

通过使用mixin类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,我们可以使用它来简化我们的views.py模块。

到这里是第二部,但是我们还是需要实例化两个类来对应两个url,为什么要实例两个类,因为每个类都有get方法,

如果不写两个类,怎么知道走哪个get方法?

第三部viewsets.ModelViewSet

url部分

1path('authors/', views.AuthorModelView.as_view({'get':'list','post':'create'}),name='authors'), 2re_path(r'^authors/(?P<pk>\d+)/$', views.AuthorModelView.as_view({'get':'retrieve', 3 'put':'update', 4 'delete':'destroy'}),name='authors_detail'), 5 6##############流程######## 7from rest_framework import viewsets 8class AuthorModelView(viewsets.ModelViewSet): 9ModelViewSet--->GenericViewSet--->ViewSetMixin----在这个类下执行了as_view 10for method, action in actions.items(): 11  #as_view后面的参数倍循环后得到了请求key,相对应的方法values 12 handler = getattr(self, action) # handler -->getattr(self,list) self--->自己写的类AuthorModelView 13 setattr(self, method, handler) #setattr(self,get,self.list) self.get---->执行self.list

view:

1from rest_framework import viewsets 2class AuthorModelView(viewsets.ModelViewSet): 3 queryset = models.Author.objects.all() 4 serializer_class = AuthorModelSerializer

认证组件

局部视图认证:

在app01.authented.py:

1from rest_framework.authentication import BaseAuthentication 2from app01 import models 3from rest_framework.exceptions import AuthenticationFailed 4 5class AuthentiCate(BaseAuthentication): 6 7 def authenticate(self, request): 8 token=request.GET.get('token') 9 token_obj=models.Token.objects.filter(token=token).first() 10 11 if not token_obj: 12 raise AuthenticationFailed('认证失败') 13 return token_obj.user.username,token_obj

在views.py:

1def get_random_str(user): 2 import hashlib,time 3 ctime=str(time.time()) 4 5 md5=hashlib.md5(bytes(user,encoding="utf8")) 6 md5.update(bytes(ctime,encoding="utf8")) 7 8 return md5.hexdigest() 9 10from app01.authented import AuthentiCate 11 12from rest_framework import viewsets 13class AuthorModelView(viewsets.ModelViewSet): 14 ##*******************### 15 authentication_classes = [AuthentiCate] 16 ##*******************### 17 queryset = models.Author.objects.all() 18 serializer_class = AuthorModelSerializer 19 20 21class LoginView(APIView): 22 23 def post(self,request): 24 ret={'status_code':1000,'msg':None} 25 try: 26 username=request.data.get('username') 27 pwd=request.data.get('pwd') 28 29 user=models.User.objects.filter(username=username,pwd=pwd).first() 30 if user: 31 radom_str=get_random_str(user.username) 32 models.Token.objects.update_or_create(user=user,defaults={'token':radom_str}) 33 ret['token']=radom_str 34 else: 35 ret['status_code']=1001 36 ret['msg']='用户名密码错误' 37 except Exception as e: 38 res["code"] = 1002 39 res["msg"] = e 40 41 return Response(data=ret)

全局视图认证组件:

在settings的配置:

1REST_FRAMEWORK={ 2 "DEFAULT_AUTHENTICATION_CLASSES":["app01.authented.AuthentiCate",] 3}

权限组件

局部权限组件:

在app01.service.permissions.py中:

1from rest_framework.permissions import BasePermission 2class SVIPPermission(BasePermission): 3 message="SVIP才能访问!" 4 def has_permission(self, request, view): 5 if request.user.user_type==3: 6 return True 7 return False

views:

1from app01.service.permissions import * 2 3class BookViewSet(generics.ListCreateAPIView): 4 permission_classes = [SVIPPermission,] 5 queryset = Book.objects.all() 6 serializer_class = BookSerializers

全局视图权限

settings.py配置如下:

1REST_FRAMEWORK={ 2 "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",], 3 "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",] 4}

如果想添加白名单,在该类下加上permission_classes =[ ]源码找的时候就会先找这里

throttle(访问频率)组件

局部视图throttle:

在app01.service.throttles.py中:

1from rest_framework.throttling import BaseThrottle 2 3VISIT_RECORD={} 4class VisitThrottle(BaseThrottle): 5 6 def __init__(self): 7 self.history=None 8 9 def allow_request(self,request,view): 10 remote_addr = request.META.get('REMOTE_ADDR') 11 print(remote_addr) 12 import time 13 ctime=time.time() 14 15 if remote_addr not in VISIT_RECORD: 16 VISIT_RECORD[remote_addr]=[ctime,] 17 return True 18 19 history=VISIT_RECORD.get(remote_addr) 20 self.history=history 21 22 while history and history[-1]<ctime-60: 23 history.pop() 24 25 if len(history)<3: 26 history.insert(0,ctime) 27 return True 28 else: 29 return False 30 31 def wait(self): 32 import time 33 ctime=time.time() 34 return 60-(ctime-self.history[-1])

在views.py中:

1from app01.service.throttles import * 2 3class BookViewSet(generics.ListCreateAPIView): 4 throttle_classes = [VisitThrottle,] 5 queryset = Book.objects.all() 6 serializer_class = BookSerializers

全局视图的throttle

1REST_FRAMEWORK={ 2 "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",], 3 "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",], 4 "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",] 5}

内置的throttle类

1class VisitThrottle(SimpleRateThrottle): 2 3 scope="visit_rate" 4 def get_cache_key(self, request, view): 5 6 return self.get_ident(request)

settings.py设置:

1REST_FRAMEWORK={ 2 "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",], 3 "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",], 4 "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",], 5 "DEFAULT_THROTTLE_RATES":{ 6 "visit_rate":"5/m", 7 } 8}

解析器

1from rest_framework.parsers import JSONParser,FormParser 2class PublishViewSet(generics.ListCreateAPIView): 3######################## 4 parser_classes = [FormParser,JSONParser] 5############################ 6 queryset = Publish.objects.all() 7 serializer_class = PublshSerializers 8 def post(self, request, *args, **kwargs): 9 print("request.data",request.data) 10 return self.create(request, *args, **kwargs)

全局:

1REST_FRAMEWORK={ 2 "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",], 3 "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",], 4 "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",], 5 "DEFAULT_THROTTLE_RATES":{ 6 "visit_rate":"5/m", 7 }, 8 "DEFAULT_PARSER_CLASSES":['rest_framework.parsers.FormParser',] 9}

URL的编写

1from django.conf.urls import url, include 2from rest_framework import routers 3from tutorial.quickstart import views 4 5router = routers.DefaultRouter() 6router.register(r'authors', views.AuthorsViewSet) 7 8 9urlpatterns = [ 10 url(r'^', include(router.urls)),

只要注册了router.register,就会有相对应的

1path('authors/',views.AuthorModelView.as_view({'get':'list','post':'create'}),name='authors'), 2re_path(r'^authors/(?P<pk>\d+)/$',views.AuthorModelView.as_view({'get':'retrieve','put':'update','delete':'destroy'}),name='authors_detail'),

并且还相应的增加了其他两条restframework的测试url

分页

分页之自定义:

第一版:

1from rest_framework.pagination import PageNumberPagination 2class Mypagination(PageNumberPagination): 3 page_size = 1 4 page_query_param = 'page' 5 page_size_query_param = "size" 6 max_page_size = 5 7 8class BookView(APIView): 9 # authentication_classes = [TokenAuth,] # [TokenAuth(),] 10 # permission_classes = [] 11 # throttle_classes = [] 12 13 def get(self,request): 14 book_list=Book.objects.all() 15 16 # 分页 17 18 pnp=Mypagination() 19 books_page=pnp.paginate_queryset(book_list,request,self) 20 21 bs=BookModelSerializers(books_page,many=True,context={'request': request}) 22 return Response(bs.data)

分页之最终版:

1from rest_framework.pagination import PageNumberPagination 2class Mypagination(PageNumberPagination): 3 page_size = 1 4 page_query_param = 'page' 5 page_size_query_param = "size" 6 max_page_size = 5 7 8from rest_framework import viewsets 9class AuthorModelView(viewsets.ModelViewSet): 10 queryset = models.Author.objects.all() 11 serializer_class = AuthorModelSerializer 12 pagination_class = Mypagination

偏移分页

from rest_framework.pagination import LimitOffsetPagination

版本的设置

1.设置settings:

1REST_FRAMEWORK={ 2 'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',#路由配置版本 3 'DEFAULT_VERSION':'v1', #默认的版本 4 'ALLOWED_VERSIONS':['v1','v2'], #允许的版本 5 'VERSION_PARAM':'version', # 版本参数

2.设置路由:
分发的时候设置:

1urlpatterns = [ 2 path('admin/', admin.site.urls), 3 re_path(r'^api/(?P<version>\w+)/', include('api.urls')), 4]

3.获取版本:

request.version #获取版本

 跨域请求CORS

1CORS: 2解决跨域的时候是加上特殊的响应头 3jsonp跨域只能是get请求, 4cors可以发送post和get请求. 5 6配置中间件 7from django.utils.deprecation import MiddlewareMixin 8class CORSMiddleware(MiddlewareMixin): 9 def process_response(self,request,response): 10 #添加响应头 11 # 允许你的域名来获取我的数据 12 # 允许所有的域名来获取数据 13 response['Access-Control-Allow-Origin']='*' 14 15 # 允许你携带Content-Type请求头 如果要多的用逗号,隔开 16 response['Access-Control-Allow-Headers']='Content-Type' 17 18 # 允许你发送DELETE,PUT 19 response['Access-Control-Allow-Methods']='DELETE,PUT' 20 21 return response 22#setting里配置 23MIDDLEWARE = [ 24'api.cors.CORSMiddleware', 25]

restful规范 猛击!

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )