教你 10 分钟构建一套 RESTful API 服务( 下 )

1. 前言

前面用了两篇文章,分别用 Java + Spring Boot 和 Python + Flask 在本地构建了一套 RESTful API 服务

本篇原计划是在上篇文章的基础上,聊聊 flask_restplus 和 Restless 依赖插件的增强使用场景的

但是,有些小伙伴希望我能写一下 Django 实现 RESTful API 的实现过程

因此本篇将介绍 Django 搭建 RESTful API 的流程 ,使用的技术栈是:Django + djangorestframework + django-rest-swagger

2. 安装依赖

使用 Django 编写 RESTful API 之前,我们需要先在虚拟环境内安装对应的依赖

具体包含:
  • Django:基础 Web 框架

  • djangorestframework:Django 的扩展,增加了对快速构建 REST API 的支持

  • django-rest-swagger:Django 支持的Swagger UI,可以生成 API 接口文档

  • django-filter:配合 djangorestframework 完成数据过滤需求

# 安装依赖
pip3 install Django
pip3 install djangorestframework

# API 可视化
pip3 install django-rest-swagger

# 配合djangorestframework使用,过滤数据( 可选 )
pip3 install django-filter

3. 准备

首先,我们使用 Pycharm 创建一个 Django 项目,并新增一个 App

为了简化过程,使用命令行连接本地 Mysql 数据库 ,并新建一个名为 rest 的数据库

然后,在项目的设置文件 settings.py 中,指定默认的数据库连接信息

# api/api/settings.py
DATABASES = {

# 默认:Mysql数据库中的rest
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'rest',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': 'localhost',
        'PORT': '3306',
    },
    'sqlite3': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

为了兼容 Django 旧版本,在项目根目录新建一个 __init__.py 文件,并指定以 PyMysql 连接数据库

# api/__init__.py
import pymysql
pymysql.install_as_MySQLdb()

接着,编辑 settings.py 文件

针对 djangorestframework,配置 App 及异常、权限、可视化、解析方式等内容

# api/api/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'django_filters',
    'restfulapi',
    'rest_framework_swagger',
]

# drf 配置,包含:异常、权限
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ],
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
    ),
    # 解析
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
    ),
    # API 可视化
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
    # 异常
    'EXCEPTION_HANDLER': 'utils.custom_execption.custom_exception_handler',
}

4. 实现

具体步骤如下:

第 1 步,编写模型,并映射数据库

新建一个类,继承自 django.db.models 中的 Model 对象,新增几个字段,指定数据类型和默认值

# api/restfulapi/models.py
from django.db import models

class Music(models.Model):
    song = models.CharField(max_length=100,default='')
    singer = models.CharField(max_length=100,default='')
    created = models.DateTimeField(auto_now_add=True)

class Meta:
        db_table = 'music'

然后,使用下面 2 条命令,将模型映射到数据,生成一张 music 表

# 映射到数据库
# 创建
python3 manage.py makemigrations  --empty  restfulapi

# 映射迁移
python3 manage.py migrate

第 2 步,序列化模型

使用 djangorestframework 提供的序列化器 ModelSerializer,将上面定义好的模型转换为其他数据格式,比如:JSON

需要注意的是,这里可以序列化所有字段,也可能只序列化一部分字段

# api/restfulapi/serializers.py
from rest_framework import serializers
from .models import Music

# 序列化模型为其他格式

class MusicSerializer(serializers.ModelSerializer):

class Meta:
        model = Music

# 序列化所有的字段
        fields = '__all__'

# 序列化部分字段
        # fields = ('id','song','singer','last_modify_date','created')

第 3 步,定义 CRUD

djangorestframework 的 ModelViewSet 定义了 CRUD 的全部功能

所以只需要编写一个 ModelViewSet 的子类,重写 create()、list()、retrieve()、update()、destory() 方法即可

当然,这里也可以使用 django_filters 来过滤数据,来完成一些复杂的查询场景

# api/restfulapi/views.py
from rest_framework import viewsets

class MusicViewSet(viewsets.ModelViewSet):
    """
    CRUD 功能
    """
    authentication_classes = []
    permission_classes = []

# 解析方式
    parser_classes = (MultiPartParser, FormParser, JSONParser)

queryset = Music.objects.all()
    serializer_class = MusicSerializer

def create(self, request, *args, **kwargs):
        """新建一条音乐"""
        pass

def list(self, request, *args, **kwargs):
        """全部音乐数据"""
        pass

def retrieve(self, request, *args, **kwargs):
        """查询一条数据"""
        pass

def update(self, request, *args, **kwargs):
        """更新一条音乐数据"""
        pass

def destroy(self, request, *args, **kwargs):
        """删除一条数据"""
        pass

第 4 步,返回数据统一化并异常处理

为了保证返回的数据结构一致,自定义 Response 和 ModelViewSet 的子类,将上面的 CRUD 进行一次封装

class JsonResponse(Response):
    """
    自定义Response,继承rest framework的Response
    """

def __init__(self, data=None, code=None, msg=None,
                 status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
        """
        Alters the init arguments slightly.
        For example, drop 'template_name', and instead use 'data'.
        Setting 'renderer' and 'media_type' will typically be deferred,
        For example being set automatically by the `APIView`.
        """
        super(Response, self).__init__(None, status=status)

if isinstance(data, Serializer):
            msg = (
                'You passed a Serializer instance as data, but '
                'probably meant to pass serialized `.data` or '
                '`.error`. representation.'
            )
            raise AssertionError(msg)

self.data = {"code": code, "message": msg, "data": data}
        self.template_name = template_name
        self.exception = exception
        self.content_type = content_type

if headers:
            for name, value in six.iteritems(headers):
                self[name] = value

异常处理:针对不存在的资源请求,不同的错误状态码,返回不同的数据

需要注意的是, settings.py 文件指定的异常处理类和该异常处理类的路径要保持一致

# 异常处理
def custom_exception_handler(exc, context):
    # Call REST framework's default exception handler first,
    # to get the standard error response.
    response = exception_handler(exc, context)

# Now add the HTTP status code to the response.
    if response is not None:
        print(response.data)
        response.data.clear()
        response.data['code'] = response.status_code
        response.data['data'] = []

if response.status_code == 404:
            try:
                response.data['message'] = response.data.pop('detail')
                response.data['message'] = "Not found"
            except KeyError:
                response.data['message'] = "Not found"

if response.status_code == 400:
            response.data['message'] = 'Input error'

elif response.status_code == 401:
            response.data['message'] = "Auth failed"

elif response.status_code >= 500:
            response.data['message'] = "Internal service errors"

elif response.status_code == 403:
            response.data['message'] = "Access denied"

elif response.status_code == 405:
            response.data['message'] = 'Request method error'
    return response

第 5 步,定义路由

在项目的 url.py 文件中,使用 DRF 中 DefaultRouter 实例对象注册,并定义路由地址

# api/api/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'music', views.MusicViewSet)

urlpatterns = [
    path('admin/', admin.site.urls),

path(r'v1.0/', include(router.urls)),
]

第 6 步,可视化

编辑第 5 步的文件,使用 rest_framework_swagger 中的 get_swagger_view() 函数,创建一个可视化的 API 界面

# api/api/urls.py
from rest_framework_swagger.views import get_swagger_view

schema_view = get_swagger_view(title='API服务')

urlpatterns = [
    url(r'^$', schema_view),
]

最后,运行项目,访问下面的链接,即可以看到定义好的 RESTful API 服务了

http://127.0.0.1:8000/

5. 最后

上面就是通过 Django +djangorestframework实现 RESTful API 完整的流程了

(0)

相关推荐

  • 测试开发你不得不学的 REST API 开发

    现在前后端分离的架构设计越来越流行,业界甚至出现了API优先的趋势.显然API开发已经成为后端程序员的必备技能了,那作为一个测试,特别是把Django作为自己主要的自动化测试平台的测试开发,Djang ...

  • Django-rest framework框架

    第一章:接口规范 01 Web应用模式 02 Restful接口规范 第二章:请求渲染解析异常响应组件 01 认识Django REST framework 02 DRF环境安装与搭建 03 DRF请 ...

  • 接口的单元测试

    作者:HelloGitHub-追梦人物 一个完整的项目,无论是个人的还是公司的,自动化的单元测试是必不可少,否则以后任何的功能改动将成为你的灾难. 假设你正在维护公司的一个项目,这个项目已经开发了几十 ...

  • Django中间件案例由浅入深+实战

    WEB前端开发社区 昨天一般概念中间件允许您在一个浏览器的请求在到达Django视图之前处理它,以及在视图返回的响应到达浏览器之前处理这个响应.Django为每个项目保留一个中间件列表.您可以在设置文 ...

  • 03 认识Django REST framework

    DRF简介 在序列化与反序列化时,虽然操作的数据不尽相同,但是执行的过程却是相似的,也就是说这部分代码是可以复用简化编写的. 在开发REST API的视图中,虽然每个视图具体操作的数据不同,但增.删. ...

  • 一文带你搞懂RESTful!

    RESTful是一种基于http方法的,很流行的API设计风格. API:应用程序编程接口,一组接口规范,客户端与服务端通过请求响应来进行数据通信. REST:表述性状态传递,决定了接口的形式与原则 ...

  • 快速创建Flask Restful API项目

    快速创建Flask Restful API项目 前言 Python必学的两大web框架之一Flask,俗称微框架.它只需要一个文件,几行代码就可以完成一个简单的http请求服务. 但是我们需要用fla ...

  • django rest swagger

    时间主题11.21(周四)20:00 契约测试&Swagger 在周四的测试运维试听课程中,芒果给大家介绍了契约测试,以及基于django rest framework 的 Swagger使用 ...

  • python测试开发django-63.基于函数的视图(@api_view())

    前言 上一篇讲了基于类的视图,在REST framework中,你也可以使用常规的基于函数的视图.它提供了一组简单的装饰器,用来包装你的视图函数, 以确保视图函数会收到Request(而不是Djang ...

  • python测试开发django-62.基于类的视图(APIView和View)

    前言 django中编辑视图views.py有两种方式,一种是基于类的实现,另外一种是函数式的实现方式,两种方法都可以用. REST框架提供了一个APIView类,它是Django View类的子类. ...