在Django 2.0中定义Web服务API接口

这是《使用Django 2.0构建Python Restful服务》第4篇

在上一章,我们介绍了使用rest-framework模块的序列化器、JSON渲染器和JSON解析器对Django模型实例进行序列化和反序列化的操作。至此,我们已经了解了如何在Django中将模型实例的数据用json数据的形式呈现出来。本章,我们将定义restful web项目的api视图函数和URL路由映射。

通过网页博客阅读,更易实践和操作

4.1 电影列表视图函数和路由映射

视图函数的定义和创建在movieapi/movies/views.py文件中进行,我们首先引入需要使用到的相关模块:

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from rest_framework import status
from movie.models import Movie
from movie.serializers import MovieSerializer

4.1.1、定义json响应类

稍微了解过Django框架的同学都知道,HttpResponse这个类返回一个字符串作为HTTP响应内容提供给浏览器。我们基于这个类,定义一个返回JSON数据作为HTTP响应内容的类:

# 继承HttpResponse类,定义一个返回json数据的响应类
class JsonResponse(HttpResponse):
    def __init__(self,data,**kwargs):
        # 重写content属性,返回rest_framework的JSON渲染器渲染的数据
        content = JSONRenderer().render(data)
        # 通过kwargs设置返回的数据类型为json
        kwargs['content_type'] = 'application/json'
        super(JsonResponse,self).__init__(content,**kwargs)

4.1.2、定义电影列表资源的视图函数

定义好json响应类之后,我们对电影列表的资源进行视图函数的创建,在电影列表资源中,我们只有两种操作:

  • GET请求用于获取电影列表;
  • POST请求用于添加电影列表;

电影列表资源的视图函数代码如下所示:

# 电影列表资源
@csrf_exempt
def movie_list(request):
    if request.method == 'GET':
        # 查询所有电影信息
        movies = Movie.objects.all()
        # 实例化一个序列化器,指示为多条数据的序列化
        movies_serializer = MovieSerializer(movies,many=True)
        # 返回序列化的json数据
        return JsonResponse(movies_serializer.data)

    elif request.method == 'POST':
        # 解析http请求的数据
        movie_data = JSONParser.parse(request)
        # 实例化一个序列化器
        movies_serializer = MovieSerializer(data=movie_data)
        # 如果序列化数据有效
        if movies_serializer.is_valid():
            movies_serializer.save()
            return JsonResponse(movies_serializer.data,status=status.HTTP_201_CREATED)
        return JsonResponse(movies_serializer.errors,status=status.HTTP_400_BAD_REQUEST)

在这个视图函数中,我们首先获取并判断http的请求方法,如果请求方法为GET,那么我们获取Movie模型的所有对象,调用序列化器MovieSerializer()对模型实例对象进行序列化,然后通过自定义的JsonResponse()类返回json数据作为HTTP响应;

如果请求方法为POST,那么我们使用json解析器JSONParser()对HTTP请求的数据进行解析,接着调用序列化器MovieSerializer()对解析后的请求数据进行序列化,如果序列化数据是有效的,那么我们调用序列化器的save()方法对数据进行保存,返回201状态码和序列化后的数据,否则返回400状态码和序列化的错误信息。

4.1.3、创建电影列表资源的路由映射

上面的电影列表资源视图函数创建好之后,我们来对其创建一条对应的url路由映射。url路由映射我们直接在moviesapi文件夹下的urls.py中进行定义:

首先,在文件中引入视图函数:

from movies.views import movie_list

然后在urlpatterns列表中添加路由规则:

urlpatterns = [
    # path('admin/', admin.site.urls),
    path('movielist/',movie_list)
]

接着,在命令行终端启动django项目:

项目运行成功后,我们使用先前下载安装的Postman进行测试。先来看看GET请求的测试:

使用GET方法对/movielist进行访问,成功地返回了电影的列表。我们再来看看POST方法的添加请求:

我们使用POST请求向服务器发送了一个json格式的数据,最终服务器返回了一条创建完成的数据记录,当我们再次使用GET请求获取所有电影列表的时候,我们刚刚使用POST传递的数据已经存在于返回的电影列表数据中了。

这样,我们的电影资源列表的两个请求方法都已经没有问题,接下来我们来创建电影详情资源的API视图函数。

4.2、电影详情视图函数和路由映射

4.2.1、电影详情视图函数

继续在movies/views.py文件中创建一个视图函数用于对电影详情进行操作:

# 电影详情资源
@csrf_exempt
def movie_detail(request,pk):
    # 首先判断是否存在相关数据
    try:
        movie = Movie.objects.get(pk=pk)
    except Movie.DoesNotExist:
        return HttpResponse(status=status.HTTP_404_NOT_FOUND)
    # 获取电影详情资源
    if request.method == 'GET':
        movie_serializer = MovieSerializer(movie)
        return JsonResponse(movie_serializer.data)

    # 修改电影详情资源
    elif request.method == 'PUT':
        movie_data = JSONParser().parse(request)
        # MovieSerializer()序列化器接收的参数的定义来源于其基类BaseSerializer
        movie_serializer = MovieSerializer(movie,data=movie_data)
        if movie_serializer.is_valid():
            movie_serializer.save()
            return JsonResponse(movie_serializer.data)
        return JsonResponse(movie_serializer.errors,status=status.HTTP_400_BAD_REQUEST)

    # 删除电影详情资源
    elif request.method == 'DELETE':
        movie.delete()
        return HttpResponse(status=status.HTTP_204_NO_CONTENT)

我们对这个请求接收一个pk参数来获取具体的模型实例对象,然后使用GET请求方法用于获取具体的电影资源,使用PUT请求方法用于修改具体的,使用DELETE方法删除具体的电影资源。

4.2.2、电影详情路由映射

创建好电影资源详情的视图函数之后,我们照例对其进行URL路由映射。在moviesapi/urls.py文件中添加URL路由与视图函数的映射关系:

path('movies/<int:pk>/',movie_detail)

添加完成后,urls.py中完整的代码如下:

from django.urls import path
from movies.views import movie_list,movie_detail

urlpatterns = [
    # path('admin/', admin.site.urls),
    path('movielist/',movie_list),
    path('movies/<int:pk>/',movie_detail)
]

4.2.3、测试电影详情API

下面我们继续使用Postman这个软件来测试我们定义的视图函数和路由映射的正确性。

首先来看GET请求方法获取电影详情资源。上一小节,我们在电影列表资源中新增了一个电影资源:

我们使用/movies/32/的GET请求方法来获取它,结果返回的就是这一个资源通过序列化器定义和转换的所有信息:

再使用PUT请求方法,修改一下它的某个字段的值,结果成功的修改并返回了修改后的值:

最后,我们使用DELETE请求方法对其进行删除:

成功地对这个资源进行了删除并返回204状态码。

这样,我们的两个资源的api就已经定义好了。

4.3 本章小结

在本章,我们简单地定义了电影列表和电影详情两个资源的api视图函数和url,并成功的使用Postman对其进行了测试。

原文发布于微信公众号 - 州的先生(zmister2016)

原文发表时间:2018-05-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏自动化测试实战

《selenium2 python 自动化测试实战》(18)——webdriver错误截图

3526
来自专栏云瓣

探寻 webpack 插件机制

webpack 可谓是让人欣喜又让人忧,功能强大但需要一定的学习成本。在探寻 webpack 插件机制前,首先需要了解一件有意思的事情,webpack 插件机制...

2727
来自专栏咸鱼不闲

post和get的区别,面试经常被问到!(二)

672
来自专栏前端黑板报

不小心栽了XML的坑

最近在做一个聊天系统,前端用的框架conversejs,传输的数据是用XML格式。在测试和预发布上基本都没有问题,可以正常的得到用户列表。

893
来自专栏java工会

Java 动态代理及 RPC 框架介绍

所谓动态代理,指的是语言提供的一种语法,能够将对对象中不同方法的调用重定向到一个统一的处理函数中来。 python重写__getattr__函数能够做到这一点,...

591
来自专栏Python中文社区

使用Python分析nginx日志

使用Python分析nginx日志 专栏作者:熊球 ♚土木工程毕业,现从事web后端开发方面的工作,擅长python,flask框架等。 博客:codechat...

20610
来自专栏知晓程序

【技术牛人分享】如何在微信小程序里实现跨页面通信?

933
来自专栏申龙斌的程序人生

零基础学编程036:快速编写一个GUI程序

在《零基础学编程035:群发邮件并不难》里,我们学会了发邮件,我用于向shenlongbin@sync.omnigroup.com发送一封邮件,就可以实现GTD...

3108
来自专栏sunseekers

Vue 父子组件数据传递( inheritAttrs + $attrs + $listeners)

当我们在书写 vue 组件的时候,也许可能会用到数据传递;将父组件的数据传递给子组件,有时候也需要通过子组件去事件去触发父组件的事件;

913
来自专栏IMWeb前端团队

Qjs直出实现过程

直出要做什么 在服务端为Qjs填充默认的值,例如 输入: <div q-text="name"></div> {"name": "Qjs"} 直出: <div ...

1918

扫码关注云+社区