视图三部曲

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

这里主要用到的是多继承


第一步mixin类编写视图

AuthorModelSerializer:
class AuthorModelSerializer(serializers.ModelSerializer):
class Meta:
model=models.Author
fields='__all__'
from rest_framework import mixins,generics
class Authors(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView):
queryset = models.Author.objects.all()
serializer_class = AuthorModelSerializer 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 AuthorsDetailView(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,generics.GenericAPIView):
queryset = models.Author.objects.all()
serializer_class = AuthorModelSerializer
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.delete(request,*args,**kwargs)

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

from rest_framework import generics

class Authors(generics.ListCreateAPIView):
queryset = models.Author.objects.all()
serializer_class = AuthorModelSerializer class AuthorsDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = models.Author.objects.all()
serializer_class = AuthorModelSerialize # class ListCreateAPIView(mixins.ListModelMixin,
# mixins.CreateModelMixin,
# GenericAPIView):
# class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
# mixins.UpdateModelMixin,
# mixins.DestroyModelMixin,
# GenericAPIView):

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

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

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

第三部viewsets.ModelViewSet

url部分

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

view:

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

认证组件

局部视图认证:

在app01.authented.py:

from rest_framework.authentication import BaseAuthentication
from app01 import models
from rest_framework.exceptions import AuthenticationFailed class AuthentiCate(BaseAuthentication): def authenticate(self, request):
token=request.GET.get('token')
token_obj=models.Token.objects.filter(token=token).first() if not token_obj:
raise AuthenticationFailed('认证失败')
return token_obj.user.username,token_obj

在views.py:

def get_random_str(user):
import hashlib,time
ctime=str(time.time()) md5=hashlib.md5(bytes(user,encoding="utf8"))
md5.update(bytes(ctime,encoding="utf8")) return md5.hexdigest() from app01.authented import AuthentiCate from rest_framework import viewsets
class AuthorModelView(viewsets.ModelViewSet):
##*******************###
authentication_classes = [AuthentiCate]
##*******************###
queryset = models.Author.objects.all()
serializer_class = AuthorModelSerializer class LoginView(APIView): def post(self,request):
ret={'status_code':1000,'msg':None}
try:
username=request.data.get('username')
pwd=request.data.get('pwd') user=models.User.objects.filter(username=username,pwd=pwd).first()
if user:
radom_str=get_random_str(user.username)
models.Token.objects.update_or_create(user=user,defaults={'token':radom_str})
ret['token']=radom_str
else:
ret['status_code']=1001
ret['msg']='用户名密码错误'
except Exception as e:
res["code"] = 1002
res["msg"] = e return Response(data=ret)

全局视图认证组件:

在settings的配置:

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

权限组件

局部权限组件:

在app01.service.permissions.py中:

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

views:

from app01.service.permissions import *

class BookViewSet(generics.ListCreateAPIView):
permission_classes = [SVIPPermission,]
queryset = Book.objects.all()
serializer_class = BookSerializers

全局视图权限

settings.py配置如下:

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

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

throttle(访问频率)组件

局部视图throttle:

在app01.service.throttles.py中:

from rest_framework.throttling import BaseThrottle

VISIT_RECORD={}
class VisitThrottle(BaseThrottle): def __init__(self):
self.history=None def allow_request(self,request,view):
remote_addr = request.META.get('REMOTE_ADDR')
print(remote_addr)
import time
ctime=time.time() if remote_addr not in VISIT_RECORD:
VISIT_RECORD[remote_addr]=[ctime,]
return True history=VISIT_RECORD.get(remote_addr)
self.history=history while history and history[-1]<ctime-60:
history.pop() if len(history)<3:
history.insert(0,ctime)
return True
else:
return False def wait(self):
import time
ctime=time.time()
return 60-(ctime-self.history[-1])

在views.py中:

from app01.service.throttles import *

class BookViewSet(generics.ListCreateAPIView):
throttle_classes = [VisitThrottle,]
queryset = Book.objects.all()
serializer_class = BookSerializers

全局视图的throttle

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

内置的throttle类

class VisitThrottle(SimpleRateThrottle):

    scope="visit_rate"
def get_cache_key(self, request, view): return self.get_ident(request)

settings.py设置:

REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
"DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
"DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",],
"DEFAULT_THROTTLE_RATES":{
"visit_rate":"5/m",
}
}

解析器

from rest_framework.parsers import JSONParser,FormParser
class PublishViewSet(generics.ListCreateAPIView):
########################
parser_classes = [FormParser,JSONParser]
############################
queryset = Publish.objects.all()
serializer_class = PublshSerializers
def post(self, request, *args, **kwargs):
print("request.data",request.data)
return self.create(request, *args, **kwargs)

全局:

REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
"DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
"DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",],
"DEFAULT_THROTTLE_RATES":{
"visit_rate":"5/m",
},
"DEFAULT_PARSER_CLASSES":['rest_framework.parsers.FormParser',]
}

URL的编写

from django.conf.urls import url, include
from rest_framework import routers
from tutorial.quickstart import views router = routers.DefaultRouter()
router.register(r'authors', views.AuthorsViewSet) urlpatterns = [
url(r'^', include(router.urls)),

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

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

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

分页

分页之自定义:

第一版:

from rest_framework.pagination import PageNumberPagination
class Mypagination(PageNumberPagination):
page_size = 1
page_query_param = 'page'
page_size_query_param = "size"
max_page_size = 5 class BookView(APIView):
# authentication_classes = [TokenAuth,] # [TokenAuth(),]
# permission_classes = []
# throttle_classes = [] def get(self,request):
book_list=Book.objects.all() # 分页 pnp=Mypagination()
books_page=pnp.paginate_queryset(book_list,request,self) bs=BookModelSerializers(books_page,many=True,context={'request': request})
return Response(bs.data)

分页之最终版:

from rest_framework.pagination import PageNumberPagination
class Mypagination(PageNumberPagination):
page_size = 1
page_query_param = 'page'
page_size_query_param = "size"
max_page_size = 5 from rest_framework import viewsets
class AuthorModelView(viewsets.ModelViewSet):
queryset = models.Author.objects.all()
serializer_class = AuthorModelSerializer
pagination_class = Mypagination

偏移分页

from rest_framework.pagination import LimitOffsetPagination

版本的设置

1.设置settings:

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

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

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

3.获取版本:

    request.version #获取版本

跨域请求CORS

CORS:
解决跨域的时候是加上特殊的响应头
jsonp跨域只能是get请求,
cors可以发送post和get请求. 配置中间件
from django.utils.deprecation import MiddlewareMixin
class CORSMiddleware(MiddlewareMixin):
def process_response(self,request,response):
#添加响应头
# 允许你的域名来获取我的数据
# 允许所有的域名来获取数据
response['Access-Control-Allow-Origin']='*' # 允许你携带Content-Type请求头 如果要多的用逗号,隔开
response['Access-Control-Allow-Headers']='Content-Type' # 允许你发送DELETE,和PUT
response['Access-Control-Allow-Methods']='DELETE,PUT' return response
#setting里配置
MIDDLEWARE = [
'api.cors.CORSMiddleware',
]

restful规范 猛击!

Django之restframework2视图三部曲的更多相关文章

  1. Django开发博客- 三部曲

    其实在django中实现一个功能只需要三个步骤即可,这里我姑且叫它三部曲. 这三部曲就是: 定义urls映射 定义views 定义templates 什么是URL? URL就算一个WEB地址,你在浏览 ...

  2. rest-framework组件 之 视图三部曲

    浏览目录 使用混合(mixins) mixin类编写视图 使用通用的基于类的视图 viewsets.ModelViewSet 视图三部曲 使用混合(mixins) from rest_framewor ...

  3. Django的View(视图)和路由系统

    一.Django的View(视图) 1.介绍 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一 ...

  4. Django Rest Framework 视图和路由

    Django Rest Framework 视图和路由   DRF的视图 APIView 我们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们 ...

  5. python 全栈开发,Day96(Django REST framework 视图,django logging配置,django-debug-toolbar使用指南)

    昨日内容回顾 1. Serializer(序列化) 1. ORM对应的query_set和ORM对象转换成JSON格式的数据 1. 在序列化类中定义自定义的字段:SerializerMethodFie ...

  6. Python学习---django重点之视图函数

    django重点之视图函数 http请求中产生两个核心对象: http请求:HttpRequest对象,由Django自己创建 http响应:HttpResponse对象,由开发自己创建,必须返回一个 ...

  7. rest-framework框架——视图三部曲

    一.mixins类编写视图 1.配置url urlpatterns = [ ... re_path(r'^authors/$', views.AuthorView.as_view(), name=&q ...

  8. Django 的 之 视图

    Django的View(视图) 一个视图函数(类),简称视图, 是个简单的python函数(类),它接受wed请求并且返回web 响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误, ...

  9. Django REST framework - 视图

    目录 Django REST framework 视图GenericAPIView GenericAPIView 例子 属性 混入 具体视图类 自定义基类 Django REST framework ...

随机推荐

  1. 转: Servlet 工作原理解析 from ibm

    评点: 比较深入的讲了servlet容器, 作者许令波 (这个文章好像来自他自己的书中java web...) https://www.ibm.com/developerworks/cn/java/j ...

  2. [Tools] Support VS Code Navigation and Autocomplete Based on Webpack Aliases with jsconfig.json

    It's common to setup Webpack aliases to make imports much more convenient, but then you lose the abi ...

  3. 从git下载一个工程

    1.右键点工程区,选“Import...” 2.Import source 选Git->“Projects from Git” 3.三个选择项中选最后一项CloneURI 4.弹出对话框,URI ...

  4. IOS 开发环境,证书和授权文件是什么?

    一.成员介绍 1.    Certification(证书) 证书是对电脑开发资格的认证,每个开发者帐号有一套,分为两种: 1)    Developer Certification(开发证书) 安装 ...

  5. iOS11

    _tab.estimatedRowHeight = 0; if (@available(iOS 11.0, *)) { //当有heightForHeader delegate时设置 _tab.est ...

  6. TCP/IP 网络编程(五)

    优于 select 的 epoll (I/O 复用) select 速度慢的原因 调用select后针对全部文件描写叙述符的循环 每次调用函数时都须要向该函数传递监视对象信息 select并非把发生变 ...

  7. 正则表达式匹配 href 和text内容

    string pattern = @"<a[^>]*href=(""(?<href>[^""]*)""|' ...

  8. ListView知识点汇总(9.2)

    1 最为基础的listview: http://www.cnblogs.com/allin/archive/2010/05/11/1732200.html http://blog.csdn.net/h ...

  9. linux 内存分析

    http://blog.yufeng.info/archives/2456  这篇文章不错 值得看 http://www.361way.com/memory-analysis/5018.html

  10. vim 批处理

    一.使用args , argdo 进行文件批处理 1. :args ./src/**/*.js         利用args命令标记所要处理的文件 2. :argdo %s/tabindex/tabI ...