est-framework框架的基本组件
rest-framework框架的基本组件
快速实例
序列化
创建一个序列化类
简单使用
开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如json
之类的表示形式的方式。我们可以通过声明与Django forms非常相似的序列化器(serializers)来实现。
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
views部分:
- 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)
ModelSerializer
- class BookSerializers(serializers.ModelSerializer):
- class Meta:
- model=Book
- fields="__all__"
- depth=1
提交post请求
- 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)
重写save中的create方法
- class BookSerializers(serializers.ModelSerializer):
- class Meta:
- model=Book
- fields="__all__"
- # exclude = ['authors',]
- # depth=1
- def create(self, validated_data):
- authors = validated_data.pop('authors')
- obj = Book.objects.create(**validated_data)
- obj.authors.add(*authors)
- return obj
单条数据的get和put请求
- class BookDetailViewSet(APIView):
- def get(self,request,pk):
- book_obj=Book.objects.filter(pk=pk).first()
- bs=BookSerializers(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)
超链接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"),
- ]
视图三部曲
使用混合(mixins)
上一节的视图部分:
- 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.ModelSerializer):
- class Meta:
- model=Book
- fields="__all__"
- #depth=1
- class PublshSerializers(serializers.ModelSerializer):
- class Meta:
- model=Publish
- fields="__all__"
- depth=1
- class BookViewSet(APIView):
- def get(self,request,*args,**kwargs):
- book_list=Book.objects.all()
- bs=BookSerializers(book_list,many=True,context={'request': request})
- return Response(bs.data)
- def post(self,request,*args,**kwargs):
- print(request.data)
- 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)
- class BookDetailViewSet(APIView):
- def get(self,request,pk):
- book_obj=Book.objects.filter(pk=pk).first()
- bs=BookSerializers(book_obj,context={'request': request})
- return Response(bs.data)
- def put(self,request,pk):
- book_obj=Book.objects.filter(pk=pk).first()
- bs=BookSerializers(book_obj,data=request.data,context={'request': request})
- if bs.is_valid():
- bs.save()
- return Response(bs.data)
- else:
- return HttpResponse(bs.errors)
- class PublishViewSet(APIView):
- def get(self,request,*args,**kwargs):
- publish_list=Publish.objects.all()
- bs=PublshSerializers(publish_list,many=True,context={'request': request})
- return Response(bs.data)
- def post(self,request,*args,**kwargs):
- bs=PublshSerializers(data=request.data,many=False)
- if bs.is_valid():
- # print(bs.validated_data)
- bs.save()
- return Response(bs.data)
- else:
- return HttpResponse(bs.errors)
- class PublishDetailViewSet(APIView):
- def get(self,request,pk):
- publish_obj=Publish.objects.filter(pk=pk).first()
- bs=PublshSerializers(publish_obj,context={'request': request})
- return Response(bs.data)
- def put(self,request,pk):
- publish_obj=Publish.objects.filter(pk=pk).first()
- bs=PublshSerializers(publish_obj,data=request.data,context={'request': request})
- if bs.is_valid():
- bs.save()
- return Response(bs.data)
- else:
- return HttpResponse(bs.errors)
mixin类编写视图
- from rest_framework import mixins
- from rest_framework import generics
- class BookViewSet(mixins.ListModelMixin,
- mixins.CreateModelMixin,
- generics.GenericAPIView):
- queryset = Book.objects.all()
- serializer_class = BookSerializers
- 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 BookDetailViewSet(mixins.RetrieveModelMixin,
- mixins.UpdateModelMixin,
- mixins.DestroyModelMixin,
- generics.GenericAPIView):
- queryset = Book.objects.all()
- serializer_class = BookSerializers
- 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.destroy(request, *args, **kwargs)
使用通用的基于类的视图
通过使用mixin类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,我们可以使用它来简化我们的views.py
模块。
- from rest_framework import mixins
- from rest_framework import generics
- class BookViewSet(generics.ListCreateAPIView):
- queryset = Book.objects.all()
- serializer_class = BookSerializers
- class BookDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
- queryset = Book.objects.all()
- serializer_class = BookSerializers
- class PublishViewSet(generics.ListCreateAPIView):
- queryset = Publish.objects.all()
- serializer_class = PublshSerializers
- class PublishDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
- queryset = Publish.objects.all()
- serializer_class = PublshSerializers
viewsets.ModelViewSet
urls.py:
- url(r'^books/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name="book_list"),
- url(r'^books/(?P<pk>\d+)$', views.BookViewSet.as_view({
- 'get': 'retrieve',
- 'put': 'update',
- 'patch': 'partial_update',
- 'delete': 'destroy'
- }),name="book_detail"),
views.py:
- class BookViewSet(viewsets.ModelViewSet):
- queryset = Book.objects.all()
- serializer_class = BookSerializers
认证与权限组件
认证组件
局部视图认证
在app01.service.auth.py:
- class Authentication(BaseAuthentication):
- def authenticate(self,request):
- token=request._request.GET.get("token")
- token_obj=UserToken.objects.filter(token=token).first()
- if not token_obj:
- raise exceptions.AuthenticationFailed("验证失败!")
- return (token_obj.user,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.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})
- 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",]
- }
权限组件
局部视图权限
在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
全局视图权限
settings.py配置如下:
- REST_FRAMEWORK={
- "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
- "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",]
- }
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类
在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",
- }
- }
解析器
request类
django的request类和rest-framework的request类的源码解析
局部视图
- 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',]
- }
分页
简单分页
- 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
- def list(self,request,*args,**kwargs):
- book_list=Book.objects.all()
- pp=LimitOffsetPagination()
- 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)
偏移分页
- from rest_framework.pagination import LimitOffsetPagination
est-framework框架的基本组件的更多相关文章
- 基于Django的Rest Framework框架的认证组件
0|1一.认证组件的作用 在一个程序中有一些功能是需要登录才能使用的,原生Django中的auth组件可以用来解决这个认证问题,drf框架中也有对应的认证组件来解决这个问题. models.py ...
- 基于Django的Rest Framework框架的频率组件
0|1一.频率组件的作用 在我们平常浏览网站的时候会发现,一个功能你点击很多次后,系统会让你休息会在点击,这其实就是频率控制,主要作用是限制你在一定时间内提交请求的次数,减少服务器的压力. modle ...
- 基于Django的Rest Framework框架的序列化组件
本文目录 一 Django自带序列化组件 二 rest-framework序列化之Serializer 三 rest-framework序列化之ModelSerializer 四 生成hypermed ...
- 基于Django的Rest Framework框架的视图组件
本文目录 一 基本视图 二 mixin类和generice类编写视图 三 使用generics 下ListCreateAPIView,RetrieveUpdateDestroyAPIView 四 使用 ...
- 基于Django的Rest Framework框架的分页组件
本文目录 一 简单分页(查看第n页,每页显示n条) 二 偏移分页(在第n个位置,向后查看n条数据) 三 CursorPagination(加密分页,只能看上一页和下一页,速度快) 回到目录 一 简单分 ...
- Django rest framework框架中有哪些组件
认证 权限(授权) 用户访问次数/频率限制 版本 解析器(parser) 序列化 分页 路由系统 视图 渲染器 认证 自定义认证的类 """ from rest_fram ...
- Django Rest framework 框架之认证使用和源码执行流程
用这个框架需要先安装: pip3 install djangorestframework 如果写了一个CBV的东西,继承了View. # 继承Django里面View class APIView(Vi ...
- ASP.NET之.NET FrameWork框架
.NET FrameWork框架 是一套应用程序开发框架,主要目的提供一个开发模型. 主要的两个组件: 公共语言运行时(Common Language Runtime)(CLR): 提供内存管理.线 ...
- Django_rest framework 框架介绍
restful介绍 restful协议 一切皆是资源,操作只是请求方式 URL 设计 原先的URL设计方式 在url 中体现出操作行为 /books/ books /books/add/ addbo ...
- Django之Rest Framework框架
一.什么是RESTful REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角度 ...
随机推荐
- django中多个app放入同一文件夹apps
开发IDE:pycharm 新建一个apps文件夹 需要整理的app文件夹拖到同一个文件夹中,即apps.(弹出对话框,取消勾选Search for references) 在pycharm 中,右键 ...
- 1.1.15 word调整文字与下划线之间的间距
先请按CTRL+U快捷键,或点击“下划线”按钮,然后输入一个空格,再输入文字“下划线间距”,在文字的尾部再添加一个空格.选中文字内容(注意不要选中首尾的空格),单击菜单“格式”→“字体”,在“字体”设 ...
- Guava 1:概览
一.引言 都说java是开源的,但是除了JDK外,能坚持更新且被广泛认可的开源jar包实在是不可多得.其中最显眼的自然是guava了,背靠google自然底气十足,今天就来解开guava的面纱,初探一 ...
- 兼容ie,火狐的判断回车键js脚本
var event = window.event || arguments.callee.caller.arguments[0]; var keycode = event.keyCode || eve ...
- C现代编程
1.C语言没有像面向对象语言一样提供访问控制的功能,无法实现数据隐藏,可以通过规定成员命名来规避这个问题,例如不允许直接访问的成员以“_”开头. 2.模板模式,利用函数指针,抽离固有代码,差异代码放到 ...
- Delphi 10-10.2.2启动提示JS错误的解决办法
HKEY_CURRENT_USER\SOFTWARE\Embarcadero\BDS\18.0\Known IDE Packages\ $(BDS)\Bin\CommunityToolbar240.b ...
- 浅读官方代码--ActionManager
用于管理节点的动作 { CCDirector* pDirector = CCDirector::sharedDirector(); //获得单例 pDirector->getActionMana ...
- ORM的多表查询详述
ORM的多表查询 ORM最核心与用的最多的地方就是跨表查询了.这里的"跨表查询"分为以下几种:基于对象的跨表查询.基于双下划线的跨表查询.聚合查询.F与Q查询以及分组查询. 下面就 ...
- phpwind v9存在命令执行漏洞(登陆后台)
已知漏洞:https://www.seebug.org/vuldb/ssvid-94465 phpwind v9最新版存在命令执行漏洞(登陆后台) Phpwind_v9.0.2(最新版),phpwin ...
- HTML/CSS基础知识(四)
WEB标准和W3C的理解与认识 Web标准是一系列标准的集合. 网页主要由三部分组成:结构(Structure).表现(Presentation)和行为(Behavior). 对应的标准也分三方面:结 ...