来聊聊这个RESTful

最近这段时间在看面试信息,很多公司的岗位要求中都有这个“掌握restful框架”。但是在我的认知里,restful好像是一种标准或者是风格啊,并不是某个具体的框架。因为自己也在这块有存疑。所以去网上寻找了一下答案。

看Url就知道要什么
看http method就知道干什么
看http status code就知道结果如何

如何理解这个REST

首先要知道全名:Representational State Transfer
逐字逐句的理解这三个单词:

  • Representational-------------表现层
    资源是一种信息实体,他可以有多种外在表现形式(例如文本可以是.txt.html.xml.json等多种格式)
    URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的".html"后缀名是不必要的,因为这个后缀名表示格式(代表一个具体的html页面),属于"表现层"范畴,而URI(我们需要的真正的资源)应该只代表"资源"的位置。它(我们请求的资源)的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述。

  • state ---------状态
  • transfer----------转换
    互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。

尽管我似乎明白了这个URI和状态转换的意义和意思,但是仍然不是“人话版本”。查询了知乎之后发现覃老师(覃超)已经在他的答案中引用了一个非常棒的解释

ivony:URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作

接下来就按照这个人话版本进行对restful的理解。

阮一峰api设计指南:http://www.ruanyifeng.com/blog/2014/05/restful_api.html

如何设计

资源就是网络上的一个实体,或者说是网络上的一个具体信息,我们使用URI(统一资源定位符)指向他,每种资源对应一个特定的URI。所谓的上网,其实就是互联网上一系列的资源互动,调用他的URI

HTTP动词:

  • GET(SELECT):从服务器取出资源(一项或多项)。
  • POST(CREATE):在服务器新建一个资源。
  • PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
  • PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
  • DELETE(DELETE):从服务器删除资源。

  • HEAD:获取资源的元数据。
  • OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。

规范样例

  • 根地址:
https://example.org/api/v1/*
https://api.example.com/v1/*
  • 版本信息:可以放在URL里面,但是也可以用HTTP的header
/api/v1/
  • URL使用名词而不是动词,推荐使用复数形式:
GET /products : will return the list of all productsPOST /products : will add a product to the collectionGET /products/4 : will retrieve product #4PATCH/PUT /products/4 : will update product #4
  • 资源地址推荐使用嵌套结构
GET /friends/10375923/profileUPDATE /profile/primaryAddress/city
  • 警惕返回结果的大小,设置分页和限制
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件
  • 使用正确的HTTP status code表示访问状态:https://link.zhihu.com/?target=http%3A//www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
  • 在返回结果用明确易懂的文本,而且适当加入注释
  • 关于安全:自己的接口就用https,加上一个key做一次hash放在最后即可。考虑到国情,HTTPS在无线网络里不稳定,可以使用Application Level的加密手段把整个HTTP的payload加密。有兴趣的朋友可以用手机连上电脑的共享Wi-Fi,然后用Charles监听微信的网络请求(发照片或者刷朋友圈)。

注意事项:
API的身份认证应该使用OAuth 2.0框架。
服务器返回的数据格式,应该尽量使用JSON,避免使用XML。

认证机制的坑

https://blog.igevin.info/posts/restful-architecture-in-general/#restful

顺带一提的Django rest framework

Django REST Framework是一个基于Django开发的APP,用于快速搭建REST API

安装

pip3 install djangorestframework

使用

注册app

settings.py

INSTALLED_APPS = [...'rest_framework',
]

注册路由

from rest_framework import routers
from . import viewsrouter = routers.DefaultRouter()
router.register(r'users', views.UserInfoViewSet)urlpatterns = [url(r'^', include(router.urls)),
]

serializers,form验证以及数据库操作

from rest_framework import serializers
from . import modelsclass UserInfoSerializer(serializers.HyperlinkedModelSerializer):class Meta:model = models.UserInfo# fields = ('id', 'username', 'pwd','ug') # fields = '__all__'exclude = ('ug',)depth = 1  # 0<=depth<=10

ViewSet视图函数

from rest_framework import viewsets
from . import models
from . import serializers# ########### 1. 基本处理方式 ###########class UserInfoViewSet(viewsets.ModelViewSet):"""API endpoint that allows users to be viewed or edited.允许用户访问查看和编辑的终端路径API"""queryset = models.UserInfo.objects.all().order_by('-id')serializer_class = serializers.UserInfoSerializer

基于CBV

url配置:

from django.conf.urls import url,include
from django.contrib import admin
from . import viewsurlpatterns = [url(r'^users/$', views.UserList.as_view()),url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
]

视图函数编写:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser
from . import models
from . import serializersclass UserList(APIView):def get(self, request, *args, **kwargs):user_list = models.UserInfo.objects.all()serializer = serializers.MySerializer(instance=user_list, many=True)return Response(serializer.data)def post(self, request, *args, **kwargs):data = JSONParser().parse(request)serializer = serializers.MySerializer(data=data)if serializer.is_valid():# print(serializer.data)# print(serializer.errors)# print(serializer.validated_data)# 如果有instance,则执行update方法;否则,执行createserializer.save()return Response(serializer.data, status=201)return Response(serializer.errors, status=400)class UserDetail(APIView):def get(self, request, *args, **kwargs):obj = models.UserInfo.objects.filter(pk=kwargs.get('pk')).first()serializer = serializers.MySerializer(obj)return Response(serializer.data)def delete(self, request, *args, **kwargs):obj = models.UserInfo.objects.filter(pk=kwargs.get('pk')).first()obj.delete()return Response(status=204)def put(self, request, *args, **kwargs):data = JSONParser().parse(request)obj = models.UserInfo.objects.filter(pk=kwargs.get('pk')).first()serializer = serializers.MySerializer(obj, data=data)if serializer.is_valid():serializer.save()return Response(serializer.data)return Response(serializer.errors, status=400)

编写seiralizers

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from . import modelsclass MySerializer(serializers.Serializer):id = serializers.IntegerField(read_only=True)username = serializers.CharField(required=False, allow_blank=True, max_length=100)pwd = serializers.CharField()def validate_username(self, value):if value == '中国':raise ValidationError('用户名中存在敏感字符')return valuedef validate_pwd(self, value):print(value)return valuedef validate(self, attrs):print(attrs)return attrsdef create(self, validated_data):"""当执行save方法时,自动调用。instance未传值:param validated_data::return:"""print(validated_data)return models.UserInfo.objects.create(**validated_data)def update(self, instance, validated_data):"""当执行save方法时,自动调用。instance传值:param instance::param validated_data::return:"""instance.username = validated_data.get('username', instance.username)instance.save()return instance

基于FBV

url

from django.conf.urls import url,include
from django.contrib import admin
from . import viewsurlpatterns = [url(r'^users/$', views.user_list),url(r'^users/(?P<pk>[0-9]+)/$', views.user_detail),
]

视图:


from django.http import JsonResponse,HttpResponse
from rest_framework.response import Response
from rest_framework.parsers import JSONParser
from rest_framework.decorators import api_view
from .serializers import MySerializer
from . import models@api_view(['GET',"POST"])
def user_list(request):"""List all code snippets, or create a new snippet."""if request.method == 'GET':user_list = models.UserInfo.objects.all()serializer = MySerializer(user_list,many=True)return Response(serializer.data)elif request.method == 'POST':data = JSONParser().parse(request)serializer = MySerializer(data=data)if serializer.is_valid():print(serializer.data)print(serializer.errors)print(serializer.validated_data)# 如果有instance,则执行update方法;否则,执行createserializer.save()return Response(serializer.data, status=201)return Response(serializer.errors, status=400)@api_view(['GET',"POST","PUT"])
def user_detail(request, pk):"""Retrieve, update or delete a code snippet."""obj = models.UserInfo.objects.filter(pk=pk).first()if not obj:return HttpResponse(status=404)if request.method == 'GET':serializer = MySerializer(obj)# return JsonResponse(serializer.data,json_dumps_params={'ensure_ascii':False},content_type='application/json;charset=utf-8')return Response(serializer.data)elif request.method == 'PUT':data = JSONParser().parse(request)serializer = MySerializer(obj, data=data)if serializer.is_valid():serializer.save()return Response(serializer.data)return Response(serializer.errors, status=400)elif request.method == 'DELETE':obj.delete()return Response(status=204)

编写serializers

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from . import modelsclass MySerializer(serializers.Serializer):id = serializers.IntegerField(read_only=True)username = serializers.CharField(required=False, allow_blank=True, max_length=100)pwd = serializers.CharField()def validate_username(self, value):if value == '中国':raise ValidationError('用户名中存在敏感字符')return valuedef validate_pwd(self, value):print(value)return valuedef validate(self, attrs):print(attrs)return attrsdef create(self, validated_data):"""当执行save方法时,自动调用。instance未传值:param validated_data::return:"""print(validated_data)return models.UserInfo.objects.create(**validated_data)def update(self, instance, validated_data):"""当执行save方法时,自动调用。instance传值:param instance::param validated_data::return:"""instance.username = validated_data.get('username', instance.username)instance.save()return instance

权限控制

settings.py配置

REST_FRAMEWORK = {'DEFAULT_PERMISSION_CLASSES': ['permissi.MyPermission',]
}

权限控制:


class MyPermission(object):"""A base class from which all permission classes should inherit."""def has_permission(self, request, view):"""Return `True` if permission is granted, `False` otherwise."""return Truedef has_object_permission(self, request, view, obj):return True

转载于:https://www.cnblogs.com/scott-lv/p/7728855.html

聊聊restful和restframework相关推荐

  1. 聊聊RESTful - 科普篇

    尊重原创,原文链接 一休: Rest, have a rest. Howard: Yeah, I have known a real REST. (本文为"聊聊RESTful"系列 ...

  2. python 软件工程_软件工程实践之 django/python

    outline 本文包括以下内容:outline django: 一个搭建后端服务的工具箱.framework: django vs flask/tornado/spring/laravel rest ...

  3. python 软件工程,软件工程实践之 django/python | 码农网

    软件工程实践系列文章, 会着重讲述实际的工程项目中是如何协作开发软件的. 本文主要介绍了 django/python 系列的 工具 链. outline 本文包括以下内容: outline djang ...

  4. REST-Framework: RESTful规范

    目录 一 什么是RESTful 二  RESTful API设计 三 基于原生的Django实现 一 什么是RESTful REST与技术无关,代表的是一种软件架构风格,REST是Representa ...

  5. 某小公司RESTful、共用接口、前后端分离、接口约定的实践

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:邵磊 juejin.im/post/59eafab36fb9 ...

  6. python flask高级编程之restful_('Python Flask高级编程之RESTFul API前后端分离精讲',),全套视频教程学习资料通过百度云网盘下载...

    资源详情 r n t某课网好评度100%的Python Flask高级编程之RESTFul API前后端分离精讲 r n t t t第1章 随便聊聊 r n t t t聊聊Flask与Django,聊 ...

  7. 接口入参形式_某小公司RESTful、共用接口、前后端分离、接口约定的实践

    点击上方"后端技术精选",选择"置顶公众号" 技术文章第一时间送达! 作者:邵磊 juejin.im/post/59eafab36fb9a045076eccc3 ...

  8. 聊聊分布式定时任务中间件架构及其实现--转

    原文来自微信公众号:聊聊架构 在互联网应用中,各式各样的定时任务存于系统各个角落.我们希望由一个平台统一将这些作业管理起来.通过这个系统,作业的宕机.崩溃等状态就可收入运维同学掌控,直接对接报警系统, ...

  9. 扬言要干掉 RESTful API 的 GraphQL 是什么鬼?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | toutiao.com/i6833818331 ...

最新文章

  1. zcmu-2149(归并排序)
  2. DirectX11 With Windows SDK--17 利用几何着色器实现公告板效果
  3. 网上花店系统源码_如何创建一个花店线上商城,可以开发一个微信小程序
  4. 拿到大厂Offer了!
  5. Ajax专题:异步交互局部刷新初步
  6. K60学习笔记一:PORT端口
  7. 自动编号转化为文本_将您的自动回复器转化为潜在客户
  8. 截止2021年7月中国有多少大学生?
  9. 【刘晓燕长难句分析】1.简单句
  10. 友达8寸高分辨率工业屏G080UAN02.2-8寸MIPI屏
  11. JAVA中用POI操作word
  12. 实验四+126+黄晟
  13. 最佳阵容 | Flutter Firebase 插件更新
  14. office PPT插件
  15. 软工专硕考研_03 2018年考研经验贴:西安交通大学软件工程专硕
  16. 杀入“黑五”战场:百度电商又一次“引体向上”
  17. PMP笔记-产品核实、范围核实及质量控制的区别
  18. [翻译] Anders Hejlsberg访谈录——Geek of the Week
  19. Linux面试题【常见】
  20. “路漫漫其修远兮,吾将上下而求索”——读“做中学”有感 20155328

热门文章

  1. install cuda on ubuntu
  2. MATLAB中的视角处理
  3. vue 随机显示数组的其中一个_两个显示器组建双屏其中一个屏幕出现重影解决方法...
  4. 图片生成html_markdown 生成头条文章的一个实现
  5. 反编译Android将状态栏高度,反编译SystemUI.apk 实现状态栏时间居中
  6. python中的sklearn教程_python作业之sklearn
  7. python读取txt文件出现UnicodeError
  8. python 需要输入多个变量_使用多个变量的Python输入验证…是否简化?
  9. 删除“ie8左侧收藏夹图标(黄星星)”及“恢复”的方法
  10. USB及手机平板设备插拔响应解决方案