rest-framework框架的基本组件

 

快速实例

Quickstart

序列化

创建一个序列化类

简单使用

开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如json之类的表示形式的方式。我们可以通过声明与Django forms非常相似的序列化器(serializers)来实现。

models部分:

  1. from django.db import models
  2.  
  3. # Create your models here.
  4.  
  5. class Book(models.Model):
  6. title=models.CharField(max_length=32)
  7. price=models.IntegerField()
  8. pub_date=models.DateField()
  9. publish=models.ForeignKey("Publish")
  10. authors=models.ManyToManyField("Author")
  11. def __str__(self):
  12. return self.title
  13.  
  14. class Publish(models.Model):
  15. name=models.CharField(max_length=32)
  16. email=models.EmailField()
  17. def __str__(self):
  18. return self.name
  19.  
  20. class Author(models.Model):
  21. name=models.CharField(max_length=32)
  22. age=models.IntegerField()
  23. def __str__(self):
  24. return self.name

views部分:

  1. from rest_framework.views import APIView
  2. from rest_framework.response import Response
  3. from .models import *
  4. from django.shortcuts import HttpResponse
  5. from django.core import serializers
  6.  
  7. from rest_framework import serializers
  8.  
  9. class BookSerializers(serializers.Serializer):
  10. title=serializers.CharField(max_length=32)
  11. price=serializers.IntegerField()
  12. pub_date=serializers.DateField()
  13. publish=serializers.CharField(source="publish.name")
  14. #authors=serializers.CharField(source="authors.all")
  15. authors=serializers.SerializerMethodField()
  16. def get_authors(self,obj):
  17. temp=[]
  18. for author in obj.authors.all():
  19. temp.append(author.name)
  20. return temp
  21.  
  22. class BookViewSet(APIView):
  23.  
  24. def get(self,request,*args,**kwargs):
  25. book_list=Book.objects.all()
  26. # 序列化方式1:
  27. # from django.forms.models import model_to_dict
  28. # import json
  29. # data=[]
  30. # for obj in book_list:
  31. # data.append(model_to_dict(obj))
  32. # print(data)
  33. # return HttpResponse("ok")
  34.  
  35. # 序列化方式2:
  36. # data=serializers.serialize("json",book_list)
  37. # return HttpResponse(data)
  38.  
  39. # 序列化方式3:
  40. bs=BookSerializers(book_list,many=True)
  41. return Response(bs.data)

ModelSerializer

  1. class BookSerializers(serializers.ModelSerializer):
  2. class Meta:
  3. model=Book
  4. fields="__all__"
  5. depth=1

提交post请求

  1. def post(self,request,*args,**kwargs):
  2.  
  3. bs=BookSerializers(data=request.data,many=False)
  4. if bs.is_valid():
  5. # print(bs.validated_data)
  6. bs.save()
  7. return Response(bs.data)
  8. else:
  9. return HttpResponse(bs.errors)

重写save中的create方法

  1. class BookSerializers(serializers.ModelSerializer):
  2.  
  3. class Meta:
  4. model=Book
  5. fields="__all__"
  6. # exclude = ['authors',]
  7. # depth=1
  8.  
  9. def create(self, validated_data):
  10.  
  11. authors = validated_data.pop('authors')
  12. obj = Book.objects.create(**validated_data)
  13. obj.authors.add(*authors)
  14. return obj

单条数据的get和put请求

  1. class BookDetailViewSet(APIView):
  2.  
  3. def get(self,request,pk):
  4. book_obj=Book.objects.filter(pk=pk).first()
  5. bs=BookSerializers(book_obj)
  6. return Response(bs.data)
  7.  
  8. def put(self,request,pk):
  9. book_obj=Book.objects.filter(pk=pk).first()
  10. bs=BookSerializers(book_obj,data=request.data)
  11. if bs.is_valid():
  12. bs.save()
  13. return Response(bs.data)
  14. else:
  15. return HttpResponse(bs.errors)

超链接API:Hyperlinked

  1. class BookSerializers(serializers.ModelSerializer):
  2. publish= serializers.HyperlinkedIdentityField(
    view_name='publish_detail',
    lookup_field="publish_id",
    lookup_url_kwarg="pk")
  3. class Meta:
  4. model=Book
  5. fields="__all__"
  6. #depth=1

urls部分:

  1. urlpatterns = [
  2. url(r'^books/$', views.BookViewSet.as_view(),name="book_list"),
  3. url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
  4. url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),
  5. url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"),
  6. ]

视图三部曲

使用混合(mixins)

上一节的视图部分:

  1. from rest_framework.views import APIView
  2. from rest_framework.response import Response
  3. from .models import *
  4. from django.shortcuts import HttpResponse
  5. from django.core import serializers
  6.  
  7. from rest_framework import serializers
  8.  
  9. class BookSerializers(serializers.ModelSerializer):
  10. class Meta:
  11. model=Book
  12. fields="__all__"
  13. #depth=1
  14.  
  15. class PublshSerializers(serializers.ModelSerializer):
  16.  
  17. class Meta:
  18. model=Publish
  19. fields="__all__"
  20. depth=1
  21.  
  22. class BookViewSet(APIView):
  23.  
  24. def get(self,request,*args,**kwargs):
  25. book_list=Book.objects.all()
  26. bs=BookSerializers(book_list,many=True,context={'request': request})
  27. return Response(bs.data)
  28.  
  29. def post(self,request,*args,**kwargs):
  30. print(request.data)
  31. bs=BookSerializers(data=request.data,many=False)
  32. if bs.is_valid():
  33. print(bs.validated_data)
  34. bs.save()
  35. return Response(bs.data)
  36. else:
  37. return HttpResponse(bs.errors)
  38.  
  39. class BookDetailViewSet(APIView):
  40.  
  41. def get(self,request,pk):
  42. book_obj=Book.objects.filter(pk=pk).first()
  43. bs=BookSerializers(book_obj,context={'request': request})
  44. return Response(bs.data)
  45.  
  46. def put(self,request,pk):
  47. book_obj=Book.objects.filter(pk=pk).first()
  48. bs=BookSerializers(book_obj,data=request.data,context={'request': request})
  49. if bs.is_valid():
  50. bs.save()
  51. return Response(bs.data)
  52. else:
  53. return HttpResponse(bs.errors)
  54.  
  55. class PublishViewSet(APIView):
  56.  
  57. def get(self,request,*args,**kwargs):
  58. publish_list=Publish.objects.all()
  59. bs=PublshSerializers(publish_list,many=True,context={'request': request})
  60. return Response(bs.data)
  61.  
  62. def post(self,request,*args,**kwargs):
  63.  
  64. bs=PublshSerializers(data=request.data,many=False)
  65. if bs.is_valid():
  66. # print(bs.validated_data)
  67. bs.save()
  68. return Response(bs.data)
  69. else:
  70. return HttpResponse(bs.errors)
  71.  
  72. class PublishDetailViewSet(APIView):
  73.  
  74. def get(self,request,pk):
  75.  
  76. publish_obj=Publish.objects.filter(pk=pk).first()
  77. bs=PublshSerializers(publish_obj,context={'request': request})
  78. return Response(bs.data)
  79.  
  80. def put(self,request,pk):
  81. publish_obj=Publish.objects.filter(pk=pk).first()
  82. bs=PublshSerializers(publish_obj,data=request.data,context={'request': request})
  83. if bs.is_valid():
  84. bs.save()
  85. return Response(bs.data)
  86. else:
  87. return HttpResponse(bs.errors)

mixin类编写视图

  1. from rest_framework import mixins
  2. from rest_framework import generics
  3.  
  4. class BookViewSet(mixins.ListModelMixin,
  5. mixins.CreateModelMixin,
  6. generics.GenericAPIView):
  7.  
  8. queryset = Book.objects.all()
  9. serializer_class = BookSerializers
  10.  
  11. def get(self, request, *args, **kwargs):
  12. return self.list(request, *args, **kwargs)
  13.  
  14. def post(self, request, *args, **kwargs):
  15. return self.create(request, *args, **kwargs)
  16.  
  17. class BookDetailViewSet(mixins.RetrieveModelMixin,
  18. mixins.UpdateModelMixin,
  19. mixins.DestroyModelMixin,
  20. generics.GenericAPIView):
  21. queryset = Book.objects.all()
  22. serializer_class = BookSerializers
  23.  
  24. def get(self, request, *args, **kwargs):
  25. return self.retrieve(request, *args, **kwargs)
  26.  
  27. def put(self, request, *args, **kwargs):
  28. return self.update(request, *args, **kwargs)
  29.  
  30. def delete(self, request, *args, **kwargs):
  31. return self.destroy(request, *args, **kwargs)

使用通用的基于类的视图

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

  1. from rest_framework import mixins
  2. from rest_framework import generics
  3.  
  4. class BookViewSet(generics.ListCreateAPIView):
  5.  
  6. queryset = Book.objects.all()
  7. serializer_class = BookSerializers
  8.  
  9. class BookDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
  10. queryset = Book.objects.all()
  11. serializer_class = BookSerializers
  12.  
  13. class PublishViewSet(generics.ListCreateAPIView):
  14.  
  15. queryset = Publish.objects.all()
  16. serializer_class = PublshSerializers
  17.  
  18. class PublishDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
  19. queryset = Publish.objects.all()
  20. serializer_class = PublshSerializers

viewsets.ModelViewSet

urls.py:

  1. url(r'^books/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name="book_list"),
  2. url(r'^books/(?P<pk>\d+)$', views.BookViewSet.as_view({
  3. 'get': 'retrieve',
  4. 'put': 'update',
  5. 'patch': 'partial_update',
  6. 'delete': 'destroy'
  7. }),name="book_detail"),

views.py:

  1. class BookViewSet(viewsets.ModelViewSet):
  2. queryset = Book.objects.all()
  3. serializer_class = BookSerializers

认证与权限组件

认证组件

局部视图认证

在app01.service.auth.py:

  1. class Authentication(BaseAuthentication):
  2.  
  3. def authenticate(self,request):
  4. token=request._request.GET.get("token")
  5. token_obj=UserToken.objects.filter(token=token).first()
  6. if not token_obj:
  7. raise exceptions.AuthenticationFailed("验证失败!")
  8. return (token_obj.user,token_obj)

在views.py:

  1. def 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.  
  10. from app01.service.auth import *
  11.  
  12. from django.http import JsonResponse
  13. class LoginViewSet(APIView):
  14. authentication_classes = [Authentication,]
  15. def post(self,request,*args,**kwargs):
  16. res={"code":1000,"msg":None}
  17. try:
  18. user=request._request.POST.get("user")
  19. pwd=request._request.POST.get("pwd")
  20. user_obj=UserInfo.objects.filter(user=user,pwd=pwd).first()
  21. print(user,pwd,user_obj)
  22. if not user_obj:
  23. res["code"]=1001
  24. res["msg"]="用户名或者密码错误"
  25. else:
  26. token=get_random_str(user)
  27. UserToken.objects.update_or_create(user=user_obj,defaults={"token":token})
  28. res["token"]=token
  29.  
  30. except Exception as e:
  31. res["code"]=1002
  32. res["msg"]=e
  33.  
  34. return JsonResponse(res,json_dumps_params={"ensure_ascii":False})

全局视图认证组件

settings.py配置如下:

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

权限组件

局部视图权限

在app01.service.permissions.py中:

  1. from rest_framework.permissions import BasePermission
  2. class 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.py:

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

全局视图权限

settings.py配置如下:

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

throttle(访问频率)组件

局部视图throttle

在app01.service.throttles.py中:

  1. from rest_framework.throttling import BaseThrottle
  2.  
  3. VISIT_RECORD={}
  4. class 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中:

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

全局视图throttle

  1. REST_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类

在app01.service.throttles.py修改为:

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

settings.py设置:

  1. REST_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. }

解析器

request类

django的request类和rest-framework的request类的源码解析

局部视图

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

全局视图

  1. REST_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. }

分页

简单分页

  1. from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
  2.  
  3. class PNPagination(PageNumberPagination):
  4. page_size = 1
  5. page_query_param = 'page'
  6. page_size_query_param = "size"
  7. max_page_size = 5
  8.  
  9. class BookViewSet(viewsets.ModelViewSet):
  10.  
  11. queryset = Book.objects.all()
  12. serializer_class = BookSerializers
  13. def list(self,request,*args,**kwargs):
  14.  
  15. book_list=Book.objects.all()
  16. pp=LimitOffsetPagination()
  17. pager_books=pp.paginate_queryset(queryset=book_list,request=request,view=self)
  18. print(pager_books)
  19. bs=BookSerializers(pager_books,many=True)
  20.  
  21. #return Response(bs.data)
  22. return pp.get_paginated_response(bs.data)

偏移分页

  1. from rest_framework.pagination import LimitOffsetPagination

est-framework框架的基本组件的更多相关文章

  1. 基于Django的Rest Framework框架的认证组件

    0|1一.认证组件的作用 在一个程序中有一些功能是需要登录才能使用的,原生Django中的auth组件可以用来解决这个认证问题,drf框架中也有对应的认证组件来解决这个问题. models.py   ...

  2. 基于Django的Rest Framework框架的频率组件

    0|1一.频率组件的作用 在我们平常浏览网站的时候会发现,一个功能你点击很多次后,系统会让你休息会在点击,这其实就是频率控制,主要作用是限制你在一定时间内提交请求的次数,减少服务器的压力. modle ...

  3. 基于Django的Rest Framework框架的序列化组件

    本文目录 一 Django自带序列化组件 二 rest-framework序列化之Serializer 三 rest-framework序列化之ModelSerializer 四 生成hypermed ...

  4. 基于Django的Rest Framework框架的视图组件

    本文目录 一 基本视图 二 mixin类和generice类编写视图 三 使用generics 下ListCreateAPIView,RetrieveUpdateDestroyAPIView 四 使用 ...

  5. 基于Django的Rest Framework框架的分页组件

    本文目录 一 简单分页(查看第n页,每页显示n条) 二 偏移分页(在第n个位置,向后查看n条数据) 三 CursorPagination(加密分页,只能看上一页和下一页,速度快) 回到目录 一 简单分 ...

  6. Django rest framework框架中有哪些组件

    认证 权限(授权) 用户访问次数/频率限制 版本 解析器(parser) 序列化 分页 路由系统 视图 渲染器 认证 自定义认证的类 """ from rest_fram ...

  7. Django Rest framework 框架之认证使用和源码执行流程

    用这个框架需要先安装: pip3 install djangorestframework 如果写了一个CBV的东西,继承了View. # 继承Django里面View class APIView(Vi ...

  8. ASP.NET之.NET FrameWork框架

    .NET FrameWork框架 是一套应用程序开发框架,主要目的提供一个开发模型. 主要的两个组件: 公共语言运行时(Common Language Runtime)(CLR): 提供内存管理.线 ...

  9. Django_rest framework 框架介绍

    restful介绍  restful协议 一切皆是资源,操作只是请求方式 URL 设计 原先的URL设计方式 在url 中体现出操作行为 /books/ books /books/add/ addbo ...

  10. Django之Rest Framework框架

    一.什么是RESTful REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角度 ...

随机推荐

  1. django中多个app放入同一文件夹apps

    开发IDE:pycharm 新建一个apps文件夹 需要整理的app文件夹拖到同一个文件夹中,即apps.(弹出对话框,取消勾选Search for references) 在pycharm 中,右键 ...

  2. 1.1.15 word调整文字与下划线之间的间距

    先请按CTRL+U快捷键,或点击“下划线”按钮,然后输入一个空格,再输入文字“下划线间距”,在文字的尾部再添加一个空格.选中文字内容(注意不要选中首尾的空格),单击菜单“格式”→“字体”,在“字体”设 ...

  3. Guava 1:概览

    一.引言 都说java是开源的,但是除了JDK外,能坚持更新且被广泛认可的开源jar包实在是不可多得.其中最显眼的自然是guava了,背靠google自然底气十足,今天就来解开guava的面纱,初探一 ...

  4. 兼容ie,火狐的判断回车键js脚本

    var event = window.event || arguments.callee.caller.arguments[0]; var keycode = event.keyCode || eve ...

  5. C现代编程

    1.C语言没有像面向对象语言一样提供访问控制的功能,无法实现数据隐藏,可以通过规定成员命名来规避这个问题,例如不允许直接访问的成员以“_”开头. 2.模板模式,利用函数指针,抽离固有代码,差异代码放到 ...

  6. Delphi 10-10.2.2启动提示JS错误的解决办法

    HKEY_CURRENT_USER\SOFTWARE\Embarcadero\BDS\18.0\Known IDE Packages\ $(BDS)\Bin\CommunityToolbar240.b ...

  7. 浅读官方代码--ActionManager

    用于管理节点的动作 { CCDirector* pDirector = CCDirector::sharedDirector(); //获得单例 pDirector->getActionMana ...

  8. ORM的多表查询详述

    ORM的多表查询 ORM最核心与用的最多的地方就是跨表查询了.这里的"跨表查询"分为以下几种:基于对象的跨表查询.基于双下划线的跨表查询.聚合查询.F与Q查询以及分组查询. 下面就 ...

  9. phpwind v9存在命令执行漏洞(登陆后台)

    已知漏洞:https://www.seebug.org/vuldb/ssvid-94465 phpwind v9最新版存在命令执行漏洞(登陆后台) Phpwind_v9.0.2(最新版),phpwin ...

  10. HTML/CSS基础知识(四)

    WEB标准和W3C的理解与认识 Web标准是一系列标准的集合. 网页主要由三部分组成:结构(Structure).表现(Presentation)和行为(Behavior). 对应的标准也分三方面:结 ...