REST framework框架组件应用一

rest_framework

Quickstart

一、序列化类(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

}

 

posted @ 2019-08-04 22:01  WiseAdministrator  阅读(151)  评论(0)    收藏  举报