从头完成一个 Restful API 服务

简介: 从头完成一个 Restful API 服务

今天一起来通过 Flask 快速完成并部署一个 Restuful 服务,不要轻易走开哦

01.框架概要

先来看看大致的代码框架

这里说明下,这套代码结构是参照经典flask书籍《Flask Web Development》来写的,想要这本书电子版的,可以联系我哈。

02.代码详解

1,依赖包

放到了requirements文件里

flask==1.0.2
flask-script==2.0.6
flask-restful==0.3.7
flask-sqlalchemy==2.3.3
flask-httpauth==3.2.4
itsdangerous==1.1.0
Flask-SQLAlchemy==2.3.2
psycopg2==2.7.6.1

2,配置文件

在config.py文件里

import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
    @staticmethod
    def init_app(app):
        pass
class DevelopmentConfig(Config):
    pass
class TestingConfig(Config):
    TESTING = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'my.sqlite3')
class ProductionConfig(Config):
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
config = {
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig
}

这里我使用了简单易用的 sqlite 数据库,当然也可以使用其他关系型数据库,比如 MySQL 等。

3,程序入口文件

manage.py

from app import create_app, db
from flask_script import Manager, Shell, Server
from app.models import User, AdminUser, Picture
app = create_app('testing')
manager = Manager(app)
def make_shell_context():
    return dict(app=app, db=db, User=User, AdminUser=AdminUser, Picture=Picture)
manager.add_command("runserver", Server(use_debugger=True, host='0.0.0.0', port='9980'))
manager.add_command("shell", Shell(make_context=make_shell_context))
if __name__ == '__main__':
    manager.run(default_command='runserver')

引入了 flask 的 command 用法,主要用来做数据库的初始化操作和快速启动 flask 服务。

4,引入蓝图

蓝图可以帮我们实现模块化应用的功能。

在主程序的__init__.py文件中创建 flask app 并注册模块

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import config
db = SQLAlchemy()
def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)
    db.init_app(app)
    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)
    from .api_1_0 import api_1_0 as api_blueprint
    app.register_blueprint(api_blueprint)
    return app

同时在 api 模块的__init__.py里引入蓝图

from flask import Blueprint
api_1_0 = Blueprint('api_1_0', __name__, url_prefix='/api')
from . import api_user, api_auth

5,表模型

models.py文件里,定义了当前用到的数据库表结构

from . import db
from werkzeug.security import generate_password_hash, check_password_hash
class AdminUser(db.Model):
    __tablename__ = 'adminuser'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(128), unique=True, index=True)
    password_hash = db.Column(db.String(128))
    @staticmethod
    def init_user():
        users = AdminUser.query.filter_by(username='admin').first()
        if users is None:
            users = AdminUser(username='admin')
        users.password = 'hardtoguess'
        db.session.add(users)
        db.session.commit()
    @property
    def password(self):
        raise AttributeError('password is not readable attribute')
    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)
    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)
    def __repr__(self):
        return "<Users {}>".format(self.username)
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(128), unique=True, index=True)
    picture_count = db.Column(db.Integer)
class Picture(db.Model):
    __tablename__ = 'pictures'
    id = db.Column(db.Integer, primary_key=True)
    picture_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    picture_name = db.Column(db.String(128))
    picture = db.Column(db.Text)

其中 AdminUser 是作为 API 的鉴权用户的存在,后面调用 API 都会使用该用户,而 User 和 Picture 则是后面需要操作的表了。

着重说下 AdminUser 类,定义了一个静态方法 init_user,是用来后面初始化数据库的,我们需要把这个鉴权用户手动添加到数据库中。方法 verify_password 用于后面 API 的鉴权,如果数据库存在该用户且密码的哈希值相同,则鉴权通过。

6,API部分

api 鉴权代码,使用 flask_httpauth 库

from flask_httpauth import HTTPBasicAuth
from flask import jsonify
from ..models import AdminUser
auth = HTTPBasicAuth()
@auth.error_handler
def unauthorized():
    error_info = '{}'.format("Invalid credentials")
    print(error_info)
    response = jsonify({'error': error_info})
    response.status_code = 403
    return response
@auth.verify_password
def verify_password(username, password):
    user = AdminUser.query.filter_by(username=username).first()
    if not user or not user.verify_password(password):
        return False
    return True

先到数据库查询用户,如果不存在或者密码哈希值不正确,则返回 False,鉴权失败。

7,设计API

api_user.py文件中,初始化 flask_restful 的 Api 类,用于后面添加 resource

api_user = Api(api_1_0)
class UserAddApi(Resource):
    @auth.login_required
    def post(self):
        user_info = request.get_json()
        try:
            u = User(username=user_info['username'])
            p = Picture(picture_name=user_info['username'])
            u.password = user_info['password']
            u.picture_count = user_info['picture_count']
            db.session.add(u)
            db.session.add(p)
            db.session.commit()
        except:
            logger.info("User add: {} failure...".format(user_info['username']))
            db.session.rollback()
            return False
        else:
            logger.info("User add: {} success...".format(user_info['username']))
            return True
        finally:
            db.session.close()
api_user.add_resource(UserAddApi, '/useradd', endpoint='useradd')

这里只接受 json 的请求消息体,并且对应的更新数据库中表的值。

03.初始化

使用在 manage 中定义的 shell 命令,进入 shell 界面

执行 db.create_all() 创建在 models 中定义的表,执行成功之后,查看数据库如下

表已经创建成功,但是我们的 admin 用户还不存在,继续执行命令 AdminUser.init_user(),插入 Admin 用户。

到此,初始化工作完毕

04.测试API

执行命令 python manage.py 启动 flask 服务,可以看到已经在本地的9980端口启动

使用 postman 工具测试 useraddAPI,选择 POST 方式,鉴权方式使用 Basic Auth,body 中使用 json 形式

发送请求测试如下:

如果修改名字或者密码为错误值,都会鉴权失败

至此,我们的一个简易 Restful 服务就搭建完成了,喜欢就点个吧~

相关文章
|
21天前
|
API 数据库 数据安全/隐私保护
利用Django框架构建高效后端API服务
本文将介绍如何利用Django框架构建高效的后端API服务。通过深入分析Django框架的特性和优势,结合实际案例,探讨了如何利用Django提供的强大功能来构建高性能、可扩展的后端服务。同时,还对Django框架在后端开发中的一些常见问题进行了解决方案的探讨,并提出了一些建设性的建议。
37 3
|
12天前
|
前端开发 Java API
构建RESTful API:Java中的RESTful服务开发
【4月更文挑战第3天】本文介绍了在Java环境中构建RESTful API的重要性及方法。遵循REST原则,利用HTTP方法处理资源,实现CRUD操作。在Java中,常用框架如Spring MVC简化了RESTful服务开发,包括定义资源、设计表示层、实现CRUD、考虑安全性、文档和测试。通过Spring MVC示例展示了创建RESTful服务的步骤,强调了其在现代Web服务开发中的关键角色,有助于提升互操作性和用户体验。
构建RESTful API:Java中的RESTful服务开发
|
16天前
|
XML JSON 安全
谈谈你对RESTful API设计的理解和实践。
RESTful API是基于HTTP协议的接口设计,通过URI标识资源,利用GET、POST、PUT、DELETE等方法操作资源。设计注重无状态、一致性、分层、错误处理、版本控制、文档、安全和测试,确保易用、可扩展和安全。例如,`/users/{id}`用于用户管理,使用JSON或XML交换数据,提升系统互操作性和可维护性。
14 4
|
24天前
|
缓存 前端开发 API
构建高效可扩展的RESTful API:后端开发的最佳实践
【2月更文挑战第30天】 在现代Web应用和服务端架构中,RESTful API已成为连接前端与后端、实现服务间通信的重要接口。本文将探讨构建一个高效且可扩展的RESTful API的关键步骤和最佳实践,包括设计原则、性能优化、安全性考虑以及错误处理机制。通过这些实践,开发者可以确保API的健壮性、易用性和未来的可维护性。
|
26天前
|
API 开发者 UED
深入探讨RESTful API设计原则及最佳实践
在当今互联网时代,RESTful API已成为各种软件系统之间进行通信的重要方式。本文将从资源定义、URI设计、HTTP方法选择、状态码规范等方面深入探讨RESTful API设计的原则与最佳实践,帮助开发者更好地构建高效、健壮的API。
|
26天前
|
JSON Java API
Springboot项目中如何设计一个规范的统一的Restful API 响应框架?
Springboot项目中如何设计一个规范的统一的Restful API 响应框架?
21 1
|
27天前
|
XML JSON API
通过Flask框架创建灵活的、可扩展的Web Restful API服务
通过Flask框架创建灵活的、可扩展的Web Restful API服务
|
28天前
|
JSON API 数据库
解释如何在 Python 中实现 Web 服务(RESTful API)。
解释如何在 Python 中实现 Web 服务(RESTful API)。
22 0
|
1月前
|
缓存 安全 测试技术
构建高效的RESTful API:后端开发的实践指南
【2月更文挑战第17天】在数字化转型的浪潮中,RESTful API已成为连接不同软件组件、实现数据交互的核心桥梁。本文将深入探讨如何构建一个高效、可扩展且安全的RESTful API,涉及设计原则、开发流程以及性能优化等关键方面。我们将透过实际案例,展示如何在保证简洁性和灵活性的同时,满足日益增长的业务需求和技术挑战。
|
2月前
|
IDE Java API
使用Java Web技术构建RESTful API的实践指南
使用Java Web技术构建RESTful API的实践指南