视图三部曲

下面我来来看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. [Angular] Debug Angular apps in production without revealing source maps

    Source: https://blog.angularindepth.com/debug-angular-apps-in-production-without-revealing-source-ma ...

  2. 2. Spring Boot返回json数据【从零开始学Spring Boot】

    在做如下操作之前,我们对之前的Hello进行简单的修改,我们新建一个包com.kfit.test.web然后新建一个类HelloControoler,然后修改App.Java类,主要是的这个类就是一个 ...

  3. 小计一次linux下渗透方法

    本文转自91ri 踩点 目标域名是XX.com 我们的目标是大站,所以主站一般都挺安全的,所以直接寻找二级目录,运气好时能找到一些开源的cms,运气更好点找到个dede啥的,那就…. 我们直接枚举他域 ...

  4. S1:适配器 Adapter

    将一个类的接口转换为用户期望的另外一个接口.适配器使得原本由于接口不兼容而不能一起工作的类可以一起工作   UML: 一.类适配器: class A { public function methodA ...

  5. Laravel之队列

    一.配置 队列配置文件存放在config/queue.php .在该文件中你将会找到框架自带的每一个队列驱动的连接配置,包括数据库.Beanstalkd. IronMQ. Amazon SQS. Re ...

  6. lodash 数组裁剪 drop

    _.drop(array, [n=1]) 裁剪数组中的前 N 个数组,返回剩余的部分. <!DOCTYPE html> <html lang="zh"> & ...

  7. 【SpringMVC学习05】SpringMVC中的参数绑定总结——较乱后期准备加入 同一篇幅他人的参数绑定

    众所周知,springmvc是用来处理页面的一些请求,然后将数据再通过视图返回给用户的,前面的几篇博文中使用的都是静态数据,为了能快速入门springmvc,在这一篇博文中,我将总结一下springm ...

  8. shader之旅-7-平面阴影(planar shadow)

    根据<real-time shadow>这本书第二章中的推导,实现了最简单的阴影技术. planar shadow通过一个投影矩阵将被灯光照射的物体的顶点沿着光线方向投影到接受阴影的平面. ...

  9. shell 判断问题总结

    #!/bin/bash #比如需要判断一个变量是否含有值: if [[ -z $1 ]] ; thenecho "Something like empty!"exit 0;fi # ...

  10. Hibernate学习之双向一对多映射(双向多对一映射)

    © 版权声明:本文为博主原创文章,转载请注明出处 1.双向映射与单向映射 - 一对多单向映射:由一方(教室)维护映射关系,可以通过教室查询该教室下的学生信息,但是不能通过学生查询该学生所在教室信息: ...