Flask RESTful API 简单的设计一个 GET 请求接口

olei 2,904 views 0
  • 数据库:PostgreSQL
  • 框架:Flask
  • 语言:Python 3.6

前提

  • 之前我有每天定时爬取bing壁纸,写入postgresql数据库的,如下:

Flask RESTful API 简单的设计一个 GET 请求接口

  • ER图

Flask RESTful API 简单的设计一个 GET 请求接口

需要的Python环境

  • flask-sqlalchemy
  • flask-migrate
  • flask-script
  • flask-restful
  • flask
  • psycopg2

创建配置文件Config.py

里面设置数据库的引擎以及其它的一些需要配置的程序参数

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 18/6/25 下午5:15
# @Author  : olei
# @File    : Config.py
# @Software: PyCharm
# @license : Copyright(C), olei.me
# @Contact : i@olei.me

DB_USER = "postgres"
DB_PASSWORD = "postgres"
HOST = "127.0.0.1"
DB_NAME = "bing"


DEBUG = True

SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_DATABASE_URI = 'postgresql://' + DB_USER + ':' + DB_PASSWORD + "@" + HOST + '/' + DB_NAME

这里设置的是postgresql的配置项

数据模型Model.py

根据数据库,来设置数据模型

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 18/6/25 下午5:22
# @Author  : olei
# @File    : Model.py
# @Software: PyCharm
# @license : Copyright(C), olei.me
# @Contact : i@olei.me

from flask_sqlalchemy import SQLAlchemy


db = SQLAlchemy()

class Bing(db.Model):
    __tablename__ = "psql_bing"
    id = db.Column(db.Integer,unique=True,primary_key=True)
    dates = db.Column(db.Date,nullable=False)
    bing_url = db.Column(db.String(10000),nullable=False)
    qiniu_url = db.Column(db.String(10000),nullable=False)
    image_name = db.Column(db.String(10000),nullable=False)

忽略我给的String的大小...,这个与flask中设计表结构的写法是一致的,用到flask的flask-sqlalchemy

数据库迁移文件migrate.py

使用Flask-Migrate和Flask-Script来实现数据迁移

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 18/6/25 下午5:25
# @Author  : olei
# @File    : migrate.py
# @Software: PyCharm
# @license : Copyright(C), olei.me
# @Contact : i@olei.me

from flask import Flask
from flask_migrate import Migrate,MigrateCommand
from flask_script import Manager
from Model import db

app = Flask(__name__)
app.config.from_object('Config')

migrate = Migrate(app,db)
manager = Manager(app)
manager.add_command('db',MigrateCommand)

if __name__ == "__main__":
    manager.run()

这里的 app.config.from_object 是读取配置文件,里面写上配置文件的没有拓展名的文件名,就是上面的配置文件Config.py 的名字

  • 定义好数据迁移配置后,执行下面命令完成数据迁移:
$ python migrate.py db init

$ python migrate.py db migrate

$ python migrate.py db upgrade

结束之后会生成一个文件夹,里面也会生成一些文件,如下:

migrations
├── README
├── alembic.ini
├── env.py
├── script.py.mako
└── versions
    └── 79d73a8da1cf_.py

Flask-RESTful接口实现app.py

  • 先给出代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 18/6/26 上午11:21
# @Author  : olei
# @File    : app.py
# @Software: PyCharm
# @license : Copyright(C), olei.me
# @Contact : i@olei.me

from flask import Flask, jsonify
from Model import db, Bing
from flask_restful import Resource, Api, reqparse, fields, marshal_with, abort, marshal

app = Flask(__name__)
app.config.from_object("Config")

db.init_app(app)

errors = {
    'BingAlreadyExistsError': {
        'message': "It is already exists.",
        'status': 409,
    },
    'ResourceDoesNotExist': {
        'message': "A resource with that ID no longer exists.",
        'status': 410,
        'extra': "Any extra information you want.",
    },
}

api = Api(app, catch_all_404s=True, errors=errors)

parser = reqparse.RequestParser()
parser.add_argument('dates', required=True)
parser.add_argument('bing_url', required=True)
parser.add_argument('qiniu_url', required=True)
# parser.add_argument('user_nickname')
parser.add_argument('image_name', required=True)

resource_full_fields = {
    'id': fields.Integer,
    'dates': fields.String,
    'bing_url': fields.String,
    'qiniu_url': fields.String,
    'image_name': fields.String
}


class Common:
    def returnTrueJson(self, data, msg="请求成功"):
        return jsonify({
            "status": 1,
            "data": data,
            "msg": msg
        })

    def returnFalseJson(self, data=None, msg="请求失败"):
        return jsonify({
            "status": 0,
            "data": data,
            "msg": msg
        })


class Hello(Resource):
    def get(self):
        return 'Hello Flask!'


class Bing_all(Resource):
    def get(self):
        # dates = Bing.query.filter_by()
        return Common.returnTrueJson(Common, marshal(Bing.query.all(), resource_full_fields))


class Bing_url(Resource):
    def get(self, dates):
        dates = Bing.query.filter_by(dates=dates).first()
        if (dates is None):
            abort(410, msg="找不到数据!", data=None, status=0)
        else:
            return Common.returnTrueJson(Common, marshal(dates, resource_full_fields))


api.add_resource(Hello, '/', '/hello')
api.add_resource(Bing_all, '/bing')
api.add_resource(Bing_url, '/bing/<string:dates>')

if __name__ == "__main__":
    app.run(debug=app.config['DEBUG'])

分析

  • 错误处理代码
errors = {
    'BingAlreadyExistsError': {
        'message': "It is already exists.",
        'status': 409,
    },
    'ResourceDoesNotExist': {
        'message': "A resource with that ID no longer exists.",
        'status': 410,
        'extra': "Any extra information you want.",
    },
}

api = Api(app, catch_all_404s=True, errors=errors)

调用是通过abort来调用的

 if (dates is None):
     abort(410, msg="找不到数据!", data=None, status=0)
  • 定义一个Common,来统一响应数据格式
  • 处理请求

Flask-RESTful的reqparse用于获取并转化客户端输入参数

parser = reqparse.RequestParser()
parser.add_argument('dates', required=True)
parser.add_argument('bing_url', required=True)
parser.add_argument('qiniu_url', required=True)
# parser.add_argument('user_nickname')
parser.add_argument('image_name', required=True)

上面代码定义了一个请求数据分析转化器(parser),然后指定参数的名称。

在获取参数数据时使用parse_args来转化所有的参数,并返回一个输入数据字典。

代码里面没有用到,这个是post,delete等请求会用到,就是增删改用

  • 处理响应

Flask-RESTful的fields用于规范响应字段,定制响应字段键名和键值数据类型,还可以对输出响应做更多复杂的处理。输出响应时,可以使用装饰器或函数式两种方式作处理:

装饰器方式:

@marshal_with(resource_full_fields, envelope=’data’)

函数方式:

marshal(User.query.all()

代码中用了函数方式来处理

运行

$ python app.py

Flask RESTful API 简单的设计一个 GET 请求接口

Flask RESTful API 简单的设计一个 GET 请求接口

Flask RESTful API 简单的设计一个 GET 请求接口

后记

忽略app.py中我对dates的处理...

  • 优化版的源码放到github上了:源码

打赏
发表评论 取消回复
表情 图片 链接 代码

分享
微信
微博
QQ