教你 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 服务了
5. 最后
上面就是通过 Django +djangorestframework实现 RESTful API 完整的流程了
我已经将文中全部源码上传到后台,关注公众号后回复「 rest3 」即可获得全部源码
如果你觉得文章还不错,请大家点赞分享下。你的肯定是我最大的鼓励和支持。
- 教你 10 分钟构建一套 RESTful API 服务( 中 )
- 教你 10 分钟构建一套 RESTful API 服务( 上 )
- Spring Cloud Spring Boot mybatis分布式微服务云架构(五)构建RESTful API
- 企业分布式微服务云SpringCloud SpringBoot mybatis (三)Spring Boot构建RESTful API与单元测试
- 企业分布式微服务云SpringCloud SpringBoot mybatis (三)Spring Boot构建RESTful API与单元测试
- 企业分布式微服务云SpringCloud SpringBoot mybatis (二十一)构建restful API
- 企业分布式微服务云SpringCloud SpringBoot mybatis (二十一)构建restful API
- SpringCloud SpringBoot mybatis 分布式微服务(三)Spring Boot构建RESTful API与单元测试
- Spring Boot构建RESTful API与单元测试
- 微服务:dubbox+zookeeper构建restful风格
- Jersey构建RESTful服务1--HelloWorld
- 实战SpringCloud响应式微服务系列教程(第八章)构建响应式RESTful服务
- SpringBoot非官方教程 | 第十一篇:springboot集成swagger2,构建优雅的Restful API
- 使用API网关构建微服务
- 使用 Spring 3 MVC HttpMessageConverter 功能构建 RESTful web 服务
- [java]构建在线restfulAPI文档之swagger2
- 使用Go构建RESTful的JSON API
- Espresso Logic的DBaas服务将SQL存储过程封装到了RESTful API中
- Spring Boot实战:Restful API的构建
- 使用 Spring 3 MVC HttpMessageConverter 功能构建 RESTful web 服务(转载)