从头完成一个restful API 服务

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

01.框架概要


先来看看大致的代码框架


image.png


先说明下,这套代码结构是参照经典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数据库。

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界面

image.png


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


image.png


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


image.png


到此,初始化工作完毕


04.测试API


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


image.png


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

image.png


image.png


发送请求测试如下:


image.png


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


image.png


04. 部署到服务器


接下来和我们前面搭建的HTTPS服务器结合到一起

把代码包上传到服务器,然后重新做一遍初始化操作,修改run.sh脚本到manage,启动,测试,完成!

相关文章
|
5天前
|
API 网络架构 UED
构建RESTful API的最佳实践
【8月更文挑战第54天】在数字化时代,RESTful API已成为连接不同软件系统、提供数据服务的关键桥梁。本文将深入探讨如何构建高效、可维护的RESTful API,涵盖设计原则、安全策略和性能优化等关键方面。通过具体代码示例,我们将一步步展示如何实现一个简洁、直观且功能强大的API。无论你是新手还是有经验的开发者,这篇文章都将为你提供宝贵的指导和启示。
54 33
|
2天前
|
缓存 监控 测试技术
深入理解RESTful API设计原则与最佳实践
【9月更文挑战第26天】在数字化时代,API(应用程序编程接口)已成为连接不同软件和服务的桥梁。本文将深入浅出地介绍RESTful API的设计哲学、六大约束条件以及如何将这些原则应用到实际开发中,以实现高效、可维护和易于扩展的后端服务。通过具体实例,我们将探索如何避免常见设计陷阱,确保API设计的优雅与实用性并存。无论你是API设计的新手还是经验丰富的开发者,这篇文章都将为你提供宝贵的指导和启示。
|
4天前
|
存储 JSON API
实战派教程!Python Web开发中RESTful API的设计哲学与实现技巧,一网打尽!
在数字化时代,Web API成为连接前后端及构建复杂应用的关键。RESTful API因简洁直观而广受欢迎。本文通过实战案例,介绍Python Web开发中的RESTful API设计哲学与技巧,包括使用Flask框架构建一个图书管理系统的API,涵盖资源定义、请求响应设计及实现示例。通过准确使用HTTP状态码、版本控制、错误处理及文档化等技巧,帮助你深入理解RESTful API的设计与实现。希望本文能助力你的API设计之旅。
24 3
|
4天前
|
存储 前端开发 API
告别繁琐,拥抱简洁!Python RESTful API 设计实战,让 API 调用如丝般顺滑!
在 Web 开发的旅程中,设计一个高效、简洁且易于使用的 RESTful API 是至关重要的。今天,我想和大家分享一次我在 Python 中进行 RESTful API 设计的实战经历,希望能给大家带来一些启发。
16 3
|
3天前
|
缓存 前端开发 API
深入浅出:RESTful API设计的最佳实践
【9月更文挑战第24天】在数字化浪潮中,API作为连接不同软件组件的桥梁,其设计质量直接影响到系统的可维护性、扩展性及用户体验。本文将通过浅显易懂的语言,结合生动的比喻和实例,带领读者深入理解RESTful API设计的核心原则与最佳实践,旨在帮助开发者构建更加健壮、灵活且用户友好的后端服务。
|
4天前
|
开发框架 JSON 缓存
震撼发布!Python Web开发框架下的RESTful API设计全攻略,让数据交互更自由!
在数字化浪潮推动下,RESTful API成为Web开发中不可或缺的部分。本文详细介绍了在Python环境下如何设计并实现高效、可扩展的RESTful API,涵盖框架选择、资源定义、HTTP方法应用及响应格式设计等内容,并提供了基于Flask的示例代码。此外,还讨论了版本控制、文档化、安全性和性能优化等最佳实践,帮助开发者实现更流畅的数据交互体验。
19 1
|
5天前
|
JSON API 开发者
惊!Python Web开发新纪元,RESTful API设计竟能如此性感撩人?
在这个Python Web开发的新纪元里,RESTful API的设计已经超越了简单的技术实现,成为了一种追求极致用户体验和开发者友好的艺术表达。通过优雅的URL设计、合理的HTTP状态码使用、清晰的错误处理、灵活的版本控制以及严格的安全性措施,我们能够让RESTful API变得更加“性感撩人”,为Web应用注入新的活力与魅力。
19 3
|
JSON API PHP
CI中如何保护RESTful API
步骤5 保护RESTful API   为了保护RESTful API,可以在application/config/rest.php中设置安全保护级别,如下所示: $config['rest_auth'] = 'basic';    其中保护级别有如下设置:   None:任何人都...
929 0
|
1月前
|
机器人 API Python
智能对话机器人(通义版)会话接口API使用Quick Start
本文主要演示了如何使用python脚本快速调用智能对话机器人API接口,在参数获取的部分给出了具体的获取位置截图,这部分容易出错,第一次使用务必仔细参考接入参数获取的位置。
114 1
|
6天前
|
安全 API 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
28 6