Django编写RESTful API(二):请求和响应
欢迎访问我的个人网站:www.comingnext.cn
前言
在上一篇文章,已经实现了访问指定URL就返回了指定的数据,这也体现了RESTful API的一个理念,每一个URL代表着一个资源。当然我们还知道RESTful API的另一个特性就是,发送不同的请求动作,会返还不同的响应,这篇文章就讲一下django-rest-framework这个工具在这方面给我们带来的便捷操作。
Request对象
平时我们在写Django的视图函数的时候,都会带上一个request参数,这样就能处理平时搭建网站时,浏览器访问网页时发出的常规的HttpRequest。但是现在我们导入了django-rest-framework,它能够对request进行拓展,并且提供更灵活的请求解析。这个特性体现在哪呢?请看下面这个例子:
request.POST # 只能处理表单数据.只能处理POST请求
request.data # 能处理各种数据。 可以处理'POST', 'PUT' 和 'PATCH'模式的请求
这个例子里面的注释已经说得很清楚,拓展后的request使用request.data就可以处理各种各样的请求了,而原本的request在处理时需要指定请求模式。
Response对象
和request对象一样,django-rest-framework也对其进行了很实用的拓展,在我上一篇文章的snippets/views.py中,我们导入了JsonResponse用于返回json格式的响应,在视图函数中是这样的:
@csrf_exempt
def snippet_list(request):
"""
列出所有已经存在的snippet或者创建一个新的snippet
"""
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return JsonResponse(serializer.data, safe=False) elif request.method == 'POST':
data = JSONParser().parse(request)
serializer = SnippetSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400)
也就是说,在return的时候就需要指明json格式,这样显得很不实用而且很单一,所以经过拓展后的Reponse对象就很方便了,它会根据客户端的请求头部信息来确定正确的内容类型以返回给客户端。只需如下代码:
return Response(data)
稍后会改进上一篇文章的程序对此进一步的具体讲解。
状态码
我们知道发送http请求时会返回各种各样的状态吗,但是都是简单的数字,比如200、404等,这些纯数字标识符有时候可能不够明确或者客户端在使用的时候不清楚错误信息甚至是没注意看不到,所以django-rest-framework也对此进行了优化,状态码会是HTTP_400_BAD_REQUEST、HTTP_404_NOT_FOUND这种,极大的提高可读性。
装饰API视图
REST框架还提供了一个装饰器和一个类来包装视图函数,可以使用它们来写API视图,让程序能处理的情况更多。
- @api_view装饰器用在基于视图的方法上。
- APIView类用在基于视图的类上。
注意:本文使用的是基于视图方法,所以使用的是装饰器@api_view,APIview这个类暂时不会提及。
这两个东西提供的一些功能,让我们省去很多工作,比如说确保你在视图中收到Request对象或在你的Response对象中添加上下文,这样就能实现内容通信。
另外装饰器可以在接收到输入错误的request.data时抛出ParseError异常,或者在适当的时候返回405 Method Not Allowed状态码。
把这些都使用起来
上面说了这么多拓展和优化,接下来就把它们都使用起来,改进一下原本的snippets/views.py,程序如下:
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer @api_view(['GET', 'POST'])
def snippet_list(request):
"""
列出所有已经存在的snippet或者创建一个新的snippet
"""
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data) elif request.method == 'POST':
serializer = SnippetSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
可以看出,经过改进的代码已经把上面所说的几个django-rest-framework带来的特性都应用起来了,我们可以看出程序代码量变少,并且能处理的情况更多了。 比如说,在原本的视图函数snippet_detail中,处理'PUT'请求的时候,需要先解析json格式的数据再进一步处理:
data = JSONParser().parse(request)
serializer = SnippetSerializer(snippet, data=data)
也就是说需要分成两步实现,而且这里有一个限制就是只能解析json格式的数据流。而改进后的程序只需一行代码:
serializer = SnippetSerializer(data=request.data)
直接使用之前说的request.data就可以获取到提交过来的数据了,并且可以处理各种数据和各种请求动作,方便了开发。
还有在return的时候也不需要指定json格式了,由原本的
return JsonResponse(serializer.data, status=201)
改成了
return Response(serializer.data,status=status.HTTP_201_CREATED)
这也意味着返回给客户端的可以是json或者html等格式的内容,返回HTML格式的内容的话,会在浏览器返回经过渲染的、更美观的页面。同时可以看出状态码也改进成了django-rest-framework给我们带来的可读性更高的状态标识码,以上这些措施都很大程度的提高了对客户的友好度。
对于另一个视图函数的修改也是同样的原理,这里就不做同样的讲解了,代码如下:
@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
"""
Retrieve, update or delete a snippet instance.
"""
try:
snippet = Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND) if request.method == 'GET':
serializer = SnippetSerializer(snippet)
return Response(serializer.data) elif request.method == 'PUT':
serializer = SnippetSerializer(snippet, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'DELETE':
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
以上就是对原有的常规的Django视图函数的改进。
总结一下就是处理request提交过来的数据不需要一定是json格式的数据,返回的响应也不需要一定是json数据,也可以是经过渲染的HTML页面。稍后就会示范使用。
向URL添加可选的格式后缀
既然上面已经说了返回给客户端的Response可是json或者是HTML等格式的内容,那么用户在使用的时候是如何指定返回哪种格式的内容呢,那就是在URL的最后加上后缀。比如http://127.0.0.1:8000/snippets.json,这样就是用户自己指定了返回json格式的Response,而不是我们在后台指定返回固定的格式。
只需对我们的程序稍加改进就可以了,在两个视图函数添加关键词参数format:
def snippet_list(request, format=None):
以及
def snippet_detail(request, pk, format=None):
再修改一下snippets/urls.py,导入format_suffix_patterns(格式后缀模式):
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
url(r'^snippets/$', views.snippet_list),
url(r'^snippets/(?P<pk>[0-9]+)$', views.snippet_detail),
] urlpatterns = format_suffix_patterns(urlpatterns)
改进后的使用
首先当然还是可以像上一篇文章中那样的使用:

也可以通过设置Accept头部信息来控制返回的格式:
http http://127.0.0.1:8000/snippets/ Accept:application/json # Request JSON
http http://127.0.0.1:8000/snippets/ Accept:text/html # Request HTML
效果如下(返回的是页面的HTML代码,只展示了一部分):

还可以直接加格式后缀:
http http://127.0.0.1:8000/snippets.json # JSON suffix
http http://127.0.0.1:8000/snippets.api # Browsable API suffix
当然啦,在命令行查看HTML代码就没啥意思了,我们可以直接在浏览器输入 http://127.0.0.1:8000/snippets.api 进行查看,会得到一个美观的页面:

如果我们要增添数据怎么办?我们可以控制 Content-Type 头部信息来提交POST请求:
http --form POST http://127.0.0.1:8000/snippets/ code="print 123"
http --json POST http://127.0.0.1:8000/snippets/ code="print 456"
它会自动在原有的数据后面添加你提交过去的数据,效果如下:

上面说了,改进后可以处理错误的提交,比如把code改成了codes,就会给出错误信息:

图中给出的错误信息是 400 Bad Request,这和我们在视图函数中定义的是一样的:
return Response(serializer.data,status=status.HTTP_400_BAD_REQUEST)
在请求中如果加入了--debug可以查看到详细的请求信息和类型:

在上面介绍@api_view和APIView的时候,提到了在适当的时候返回405 Method Not Allowed状态码。这个所谓适当的时候就要回看到刚才写视图函数的时候,修饰器的代码:
@api_view(['GET','POST'])
以及
@api_view(['GET','PUT','DELETE'])
这两行代码就规定了在调用这两个函数,也就是访问到相关的URL时,只能使用指定的请求动作,否则就会报出405 Method Not Allowed错误。例如访问 http://127.0.0.1:8000/snippets.json 时用了PUT请求就会报这个错:

正确的更改数据应该如下:
http --json PUT http://127.0.0.1:8000/snippets/1.json code="hello world"

这样就把 id=1 的数据修改了。想要删除也是一样的:

这样就可以把 id=3 的数据删除掉了。
OK,关于Django RESTful API的请求和响应部分的处理就先讲到这了。下一篇会介绍基于类的视图,多谢支持~
本文地址:http://www.cnblogs.com/zivwong/p/7427394.html
作者博客:ziv
欢迎转载,请在明显位置给出出处及链接
Django编写RESTful API(二):请求和响应的更多相关文章
- Django编写RESTful API(一):序列化
欢迎访问我的个人网站:www.comingnext.cn 关于RESTful API 现在,在开发的过程中,我们经常会听到前后端分离这个技术名词,顾名思义,就是前台的开发和后台的开发分离开.这个技术方 ...
- Django编写RESTful API(四):认证和权限
欢迎访问我的个人网站:www.comingnext.cn 前言: 按照前面几篇文章里那样做,使用Django编写RESTful API的基本功能已经像模像样了.我们可以通过不同的URL访问到不同的资源 ...
- Spring Boot 2.x 编写 RESTful API (二) 校验
用Spring Boot编写RESTful API 学习笔记 约束规则对子类依旧有效 groups 参数 每个约束用注解都有一个 groups 参数 可接收多个 class 类型 (必须是接口) 不声 ...
- Django编写RESTful API(三):基于类的视图
欢迎访问我的个人网站:www.comingnext.cn 前言 在上一篇文章中,主要讲的是请求和响应,项目里面views.py中的视图函数都是基于函数的,并且我们介绍了@api_view这个很有用的装 ...
- Django编写RESTful API(六):ViewSets和Routers
欢迎访问我的个人网站:www.comingnext.cn 前言 在本系列的文章中,我在第一篇和第二篇文章中写的编写Django视图时,使用的都是基于函数的方法,并且每个视图函数之前都会加一个djang ...
- Django编写RESTful API(五):添加超链接提高模型间的关联性
前言 在第四篇中,加入了用户模型,以及相关的认证和权限的功能.但是我们在使用的时候,会发现在访问http://127.0.0.1:8000/users/时看到的用户列表,不能够直接点击某个链接然后查看 ...
- 利用 Django REST framework 编写 RESTful API
利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framewor ...
- RESTful规范与django编写restful接口
一.什么是RESTful规范 ①REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” ②REST从资 ...
- python 全栈开发,Day95(RESTful API介绍,基于Django实现RESTful API,DRF 序列化)
昨日内容回顾 1. rest framework serializer(序列化)的简单使用 QuerySet([ obj, obj, obj]) --> JSON格式数据 0. 安装和导入: p ...
随机推荐
- RabbitMQ系列教程之六:远程过程调用(RPC)
远程过程调用(Remote Proceddure call[RPC])(本实例都是使用的Net的客户端,使用C#编写) 在第二个教程中,我们学习了如何使用工作队列在多个工作实例之间分配耗时的任务. ...
- vue-roter2 路由传参
本文主要介绍通过vue-router2路由中传参的方法,项目为vue-cli搭建项目 1.路由配置 首先在路由配置处(router/index.js), 在path后面通过:+参数名来指定参数名 需要 ...
- JavaScript跨域请求和jsonp请求实例
<script type="text/javascript" src="./whenReady.js"></script> <sc ...
- PHP获取文件夹中的所有文件(包括子目录)
方法一: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function tree($directory) ...
- 号称精通Java的你,是否真的名副其实
慎用精通 随着猎头行业的兴盛,一些应聘者往往可以从猎头那得到一些注意事项和过往经验.比如,在简历中切不可随意用上"精通"二字,尤其对于刚入职场的小伙伴. 因为,对于应聘者写上精通和 ...
- pug模板引擎(原jade)
前面的话 为什么要引入pug,pug有什么特别之处呢?有一些嵌套层次较深的页面,可能会出现巢状嵌套,如下图所示 在后期维护和修改时,一不小心少了一个尖括号,或者某个标签的开始和闭合没有对应上,就会导致 ...
- 设计模式(3)抽象工厂模式(Abstract Factory)
设计模式(0)简单工厂模式 设计模式(1)单例模式(Singleton) 设计模式(2)工厂方法模式(Factory Method) 源码地址 0 抽象工厂模式简介 0.0 抽象工厂模式定义 抽象工厂 ...
- (转)Linux命令grep
场景:grep命令在文件搜索中经常会使用到,所以熟练掌握该命令对于日常日志搜索相当有必要! Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.g ...
- Linux日志分析ELK环境搭建
场景:ELK作为一个日志收集和检索系统,感觉功能还是相当的强大的. ELK是啥, 其实是是三个组件的缩写, 分别是elasticsearch, logstash, kibana. ELK平台可以用于实 ...
- (转)linux中项目部署和日志查看
1 查找进程 ps -ef | grep java 查看所有关于java的进程 root 17540 1 0 2009 ? 01:42:27 /usr/java/ ...