当前位置:   article > 正文

利用Flask搭建API应用服务器

flask搭建api

应用场景

      以电子商场为例,不同的电子商铺,货源完全有可能来源于同一个厂家。店铺只完成销售和付款,发货和物流完由厂家完成。这部分厂家的工作内容,相对于电子商城来说,属于应用服务器。

应用服务器和web服务器的不同点

        完整的web商城要同时解决,商城展示和数据管理两部分工作。而应用服务器只完成数据的处理和管理,而前端展示完全交给商家去做。这样,就很容易保持商品数据一致性的情况下。实现,用不同的方式在不同的店铺进行销售。

服务器文件结构

  1. ├─apps
  2. ├─api # 供应链物流API
  3. ├─db 数据库
  4. ├─lib 自定义插件

程序介绍

主程序  main.py

  1. from apps import create_app
  2. app = create_app()
  3. if __name__ == '__main__':
  4. app.run(host='0.0.0.0', port=8360)

主程序初始化

 利用 flask API 创建 应用服务器,必须启动如下服务。

  •  数据库服务
  •  登录认证服务
  •  API端口服务
  •  跨域范围服务(第三方授权商城访问)

   这些服务必须跟随主程序启动时,一起激活。并且一个主程序,对同一类服务不能重复激活。

  1. # 1.1 引入FLask 框架主函数
  2. import click
  3. from flask import Flask
  4. # 1.2 引入数据库(数据库不能共搜)
  5. from db.external import db
  6. import db.external as external
  7. # 1.3 引入登录验证机制和配置参数
  8. from flask_migrate import Migrate
  9. from lib.decorators import login_manager
  10. from . import config
  11. # 1.4 设置跨网站访问机制CORS
  12. from flask_cors import CORS
  13. # 创建主程序
  14. def create_app():
  15. web = Flask(__name__, static_folder="../static", template_folder="../templates", static_url_path='/', )
  16. web.config.from_object(config) # 导入配置文件
  17. web.config.from_object(external)
  18. register_extensions(web) # 初始化对象
  19. register_blueprints(web) # API蓝本
  20. CORS(web, resources={r"/*": {"origins": "*"}} ) # sh
  21. return web
  22. def register_extensions(app):
  23. db.init_app(app)
  24. Migrate(app,db)
  25. login_manager.init_app(app)
  26. def register_blueprints(app):
  27. from apps.api import API_V1
  28. app.register_blueprint(API_V1, url_prefix='/' + app.config["API_POST"]) # 主视图函数蓝本
  29. def register_commands(app):
  30. pass

数据库服务 external.py

  1. #encoding:utf-8
  2. from flask_sqlalchemy import SQLAlchemy #导入SQLAlchemy模块
  3. #此时先不传入app 数据库初始化
  4. db = SQLAlchemy()
  5. HOST = '你自己的数据库地址'
  6. PORT = '你自己的数据库端口'
  7. USERNAME = 'root'
  8. PASSWORD = '******'
  9. # DATABASE = 'mysql'
  10. DATABASE = 'apex_shop'
  11. DB_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset-utf8'.format(username=USERNAME,
  12. password=PASSWORD,
  13. host=HOST,
  14. port=PORT,
  15. db=DATABASE)
  16. SQLALCHEMY_DATABASE_URI = DB_URI
  17. SQLALCHEMY_TRACK_MODIFICATIONS = False
  18. SQLALCHEMY_ECHO = False
  19. FLASKY_DB_QUERY_TIMEOUT=0.00005 #数据库查询时间的门限值

 系统配置文件 config.py

  1. from datetime import timedelta
  2. import random
  3. # 这个是FLASK服务端的秘钥
  4. SECRET_KEY = str(random.randint(100000, 999999))
  5. EXPIRY_HOURS = 15
  6. REFRESH_DAYS = 14
  7. API_POST = 'api'

 API 端口服务 

flask 对于页面数据或应用数据,提供了蓝图模式。蓝图相当于仓库,不同的仓库可以管理不同的API应用。这里我们把对外API单独定为一个蓝图。

  1. def register_blueprints(app):
  2. from apps.api import API_V1
  3. app.register_blueprint(API_V1, url_prefix='/' + app.config["API_POST"]) # 主视图函数蓝本

 flask 默认的API路由写法 是

  1. @app.route('/hello',method=["GET","POST"])
  2. def hello():
  3. return .....

  这种写法比较简单,但是在判断不同请求方式(GET、POST)撰写比较麻烦。

 这里我们采用另一种 flask_restful 的抒写方式。这种方式是把每个路由定义成一个类,列下面有get、post函数 来区不同的访问方法。

下面是写法参考。

  1. class AuthGroup(Resource):
  2. def __init__(self):
  3. pass
  4. def post(self,methods):
  5. if methods == 'get.auth.group.list':
  6. role = Role.query.all()
  7. items = []
  8. for item in role:
  9. items.append({
  10. "group_id": item.id,
  11. "name": item.name,
  12. "description": item.description,
  13. "system": 1,
  14. "sort": 50,
  15. "status": 1
  16. })
  17. return jsonify(items)

 flask 登录验证

 flask 最成熟的登录模块是 flask_login,它支持 用户名密码登录和TOKEN登录两种方式。

 这里适合采用,TOKEN方式。下面简述一下。TOKEN登录的原理。详解在后续文章中描述。

  1. from functools import wraps
  2. from flask import session,redirect,url_for,request,jsonify,Markup,flash,abort,current_app,g
  3. from db.models import User,Guest
  4. from flask_login import LoginManager,login_user,logout_user,login_required,current_user,UserMixin
  5. from apps.model import Token
  6. import lib.base as base
  7. import json
  8. import apps.redis as rd
  9. import time
  10. #访问控制
  11. # 实例化LoginManager类
  12. login_manager = LoginManager()
  13. # 提示信息
  14. login_manager.login_message = "请先登录"
  15. # 提示样式
  16. login_manager.login_message_category = 'danger'
  17. login_manager.anonymous_user = Guest
  18. class bcolors:
  19. HEADER = '\033[95m'
  20. OKBLUE = '\033[94m'
  21. OKGREEN = '\033[92m'
  22. WARNING = '\033[93m'
  23. FAIL = '\033[91m'
  24. ENDC = '\033[0m'
  25. BOLD = '\033[1m'
  26. UNDERLINE = '\033[4m'
  27. def load_token(tok):
  28. """通过loads()方法来解析浏览器发送过来的token,从而进行初步的验证"""
  29. try:
  30. api_key = Token.validate_token(tok)
  31. user = User.query.get(api_key.get('user_id'))
  32. except Exception as e:
  33. return None
  34. if user:
  35. user.token = tok
  36. else:
  37. print('用户不存在,令牌不正确!')
  38. return None
  39. return user
  40. def get_token_key(key):
  41. """解密token到数据"""
  42. try:
  43. key = key.replace('Basic ', '', 1)
  44. key = key.encode('utf-8')
  45. key = Token.validate_token(key)
  46. except TypeError:
  47. return None
  48. return key
  49. def get_key(value):
  50. if value == '':
  51. value = None
  52. return value
  53. @login_manager.unauthorized_handler
  54. def unauthorized():
  55. """系统超时退出"""
  56. return jsonify(base.get_result(401,'系统退出2'))
  57. @login_manager.request_loader
  58. def load_user_from_request(request):
  59. """效验请求中的token"""
  60. if request.method == "POST":
  61. g.refresh = False
  62. """# 请求正文中携带token时,执行如下代码
  63. 捕捉请求参数中的 'api_key' 变量,这个api_key和数据库中存储的api_key比较,确认登录身份。
  64. """
  65. api_access_key = request.args.get('api_key')
  66. if api_access_key:
  67. user = User.query.filter_by(api_key=api_access_key).first()
  68. if user:
  69. return user
  70. """请求头中携带token,执行如下代码
  71. 捕捉请求参数中的 'X-Token' 变量,这个Access-Token通过服务端解码后,获得用户ID和Access-Token有效期,确认登录身份。
  72. """
  73. # 取请求头中的access-token
  74. api_access_key = get_key(request.headers.get('Access-Token'))
  75. api_refresh_key = get_key(request.headers.get('Refresh-Token'))
  76. # 对比前端的token和服务器中保存的token是否一致,判断用户是否已经登录了
  77. if api_access_key:
  78. login_data = get_token_key(api_access_key)
  79. Refresh_data = get_token_key(api_refresh_key)
  80. # 判断token是否过期,没有过期返回用户对象。
  81. if login_data and api_access_key == get_key(
  82. rd.get_redis_data('front_access_token' + '_' + str(login_data.get('user_id')))):
  83. g.user = User.query.get(login_data.get('user_id'))
  84. return g.user
  85. # 判断如果token已经过期了,但是front_refresh_token没有过期,执行如下代码?
  86. elif Refresh_data:
  87. login_data = get_token_key(get_key(request.headers.get('Refresh-Token')))
  88. refresh_key = get_token_key(
  89. rd.get_redis_data('front_refresh_token' + '_' + str(login_data.get('user_id'))))
  90. g.user = User.query.get(refresh_key.get('user_id'))
  91. g.refresh = True
  92. return g.user
  93. return None
  94. return None

启动程序

在CMD 中输入  flask run

这是通过浏览器访问 http:// 自己的服务器地址:自定义端口。就可以方法这个服务器获取数据了

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/507729
推荐阅读
相关标签
  

闽ICP备14008679号