REST framework框架组件应用一
rest_framework
一、序列化类(Serializer)
开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如json之类的表示形式的方式。我们可以通过声明与Django forms非常相似的序列化器来实现。
models数据表设计:
from django.db import models # Create your models here. # 书籍表 class Book(models.Model): title=models.CharField(max_length=32) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") authors=models.ManyToManyField("Author") def __str__(self): return self.title
# 出版社表 class Publish(models.Model): name=models.CharField(max_length=32) email=models.EmailField() def __str__(self): return self.name
# 作者表 class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() def __str__(self): return self.name
1.1 序列化器类Serializer:
序列化器类:
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse
from django.core import serializers
from rest_framework import serializers
class BookSerializers(serializers.Serializer):
title=serializers.CharField(max_length=32)
price=serializers.IntegerField()
pub_date=serializers.DateField()
publish=serializers.CharField(source="publish.name")
#authors=serializers.CharField(source="authors.all")
authors=serializers.SerializerMethodField()
def get_authors(self,obj):
temp=[]
for author in obj.authors.all():
temp.append(author.name)
return temp
视图类实现:
# 书籍的视图类
class BookViewSet(APIView): # 获取书籍信息 def get(self,request,*args,**kwargs): book_list=Book.objects.all() # 序列化方式1: # from django.forms.models import model_to_dict # import json # data=[] # for obj in book_list: # data.append(model_to_dict(obj)) # print(data) # return HttpResponse("ok") # 序列化方式2: # data=serializers.serialize("json",book_list) # return HttpResponse(data) # 序列化方式3: bs=BookSerializers(book_list,many=True) return Response(bs.data)
# 创建新书籍 def post(self, request, *args, **kwargs): bs = BookSerializers(data=request.data, many=False) if bs.is_valid(): # print(bs.validated_data) bs.save() return Response(bs.data) else: return HttpResponse(bs.errors)
1.2 序列化器ModelSerializer:
class BookSerializers(serializers.ModelSerializer):
class Meta:
model=Book
fields="__all__" # 获取数据库表中所有数据
depth=1 # 序列递归深度
1.3 重写save中的create方法
class BookSerializers(serializers.ModelSerializer):
class Meta:
model=Book
fields="__all__"
# exclude = ['authors',]
# depth=1
# 重写父类create方法
# 用于数据处理
def create(self, validated_data):
authors = validated_data.pop('authors') # 获取作者信息
obj = Book.objects.create(**validated_data)
obj.authors.add(*authors) # 正向添加书籍的作者信息
return obj
1.4 单条数据的get和put请求
# 书籍详情页视图类
class BookDetailViewSet(APIView): # 获取单条的书籍信息 def get(self,request,pk): book_obj=Book.objects.filter(pk=pk).first() bs=BookSerializers(instance=book_obj) return Response(bs.data)
# 更新单条书籍信息 def put(self,request,pk): book_obj=Book.objects.filter(pk=pk).first() bs=BookSerializers(book_obj,data=request.data) if bs.is_valid(): bs.save() return Response(bs.data) else: return HttpResponse(bs.errors)
1.5 超链接API:Hyperlinked
# 书籍序列化器
class BookSerializers(serializers.ModelSerializer): publish= serializers.HyperlinkedIdentityField(
view_name='publish_detail',
lookup_field="publish_id",
lookup_url_kwarg="pk") class Meta: model=Book fields="__all__" #depth=1
urls路由分发部分:
urlpatterns = [ url(r'^books/$', views.BookViewSet.as_view(),name="book_list"), url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"), url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"), url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"), ]
二、认证组件
自定义认证组件类:
在app01.service.auth.py:
# 自定义认证组件
class Authentication(BaseAuthentication):
# 重写父类方法 def authenticate(self,request): token=request._request.GET.get("token") # 获取查询字符串token值 token_obj=UserToken.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed("验证失败!")
return (token_obj.user,token_obj) # 认证成功,返回用户名和token值
在views.py:
# md5加密
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.service.auth import * from django.http import JsonResponse
# 用户登录视图 class LoginViewSet(APIView):
# 当前视图使用自定义认证类 authentication_classes = [Authentication,]
def post(self,request,*args,**kwargs): res={"code":1000,"msg":None} try: user=request._request.POST.get("user") pwd=request._request.POST.get("pwd") user_obj=UserInfo.objects.filter(user=user,pwd=pwd).first() print(user,pwd,user_obj) if not user_obj: res["code"]=1001 res["msg"]="用户名或者密码错误" else: token=get_random_str(user) UserToken.objects.update_or_create(user=user_obj,defaults={"token":token}) # 更新数据库中的token值 res["token"]=token except Exception as e: res["code"]=1002 res["msg"]=e return JsonResponse(res,json_dumps_params={"ensure_ascii":False})
全局视图认证组件配置:
如果想把自定义的组件应用到所有的视图类,则settings.py配置如下:
REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",] # 自定义认证组件路径 }
三、权限组件
3.1 自定义局部视图权限
在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.py:
from app01.service.permissions import *
# 视图类 class BookViewSet(generics.ListCreateAPIView):
# 局部配置自定义组件 permission_classes = [SVIPPermission,]
queryset = Book.objects.all() serializer_class = BookSerializers
3.2 全局视图权限配置:
settings.py配置如下:
# 全局配置
REST_FRAMEWORK={
# 权限组件路径 "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",] }
四、频率组件
4.1 局部视图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
4.2 全局视图throttle配置
# 全局配置(应用于所有视图)
REST_FRAMEWORK={ "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",] }
4.3 内置throttle类
在app01.service.throttles.py修改为:
# 继承内置频率组件
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", # 每分钟5次访问频率
}
}
五、解析器组件
django的request类和rest-framework的request类的源码解析
5.1 局部视图配置
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)
5.2 全局视图配置
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',]
}
六、分页组件
自定义简单分页:
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
# 自定义分页 class PNPagination(PageNumberPagination): page_size = 1 page_query_param = 'page' page_size_query_param = "size" max_page_size = 5
# 视图类 class BookViewSet(viewsets.ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializers
# 重写父类的list方法 def list(self,request,*args,**kwargs): book_list=Book.objects.all() pp=LimitOffsetPagination() # 实例化分页类(restful内部分页器) pager_books=pp.paginate_queryset(queryset=book_list,request=request,view=self) print(pager_books) bs=BookSerializers(pager_books,many=True) #return Response(bs.data) return pp.get_paginated_response(bs.data)
再settings.py文件中配置分页数:
REST_FRAMEWORK = { # 定义分页大小 "PAGE_SIZE": 2 }
https://www.cnblogs.com/WiseAdministrator/

浙公网安备 33010602011771号