__init__.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. """
  2. 期货数据管理系统的Flask应用包
  3. """
  4. import os
  5. import yaml
  6. import click
  7. from flask import Flask
  8. from app.database.db_manager import db, migrate, init_db
  9. from app.routes.future_info import bp as future_info_bp
  10. from app.routes.transaction import bp as transaction_bp
  11. from app.routes.trade import bp as trade_bp
  12. from app.routes.monitor import bp as monitor_bp
  13. from app.routes.dimension import bp as dimension_bp
  14. def _update_flask_config_from_service(app):
  15. """
  16. 从配置服务更新Flask应用配置
  17. 在数据库初始化完成后调用,尝试从配置数据库更新Flask配置
  18. """
  19. try:
  20. with app.app_context():
  21. from app.services.config_service import get_str_config, get_bool_config
  22. # 更新支持热更新的配置
  23. secret_key = get_str_config('flask_secret_key', app.config.get('SECRET_KEY', 'dev'))
  24. if secret_key and secret_key != 'dev': # 只有在非默认值时才更新
  25. app.config['SECRET_KEY'] = secret_key
  26. print(f"Flask SECRET_KEY 已从配置服务更新")
  27. # 更新SQLAlchemy配置
  28. track_modifications = get_bool_config('sqlalchemy_track_modifications', False)
  29. app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = track_modifications
  30. # 数据库URI通常不支持热更新,但我们可以记录当前配置
  31. db_prefix = get_str_config('database_uri_prefix', 'sqlite:///')
  32. print(f"数据库配置已确认: 前缀={db_prefix}, 追踪修改={track_modifications}")
  33. except Exception as e:
  34. print(f"从配置服务更新Flask配置失败,继续使用默认配置: {e}")
  35. def _initialize_config_service(app):
  36. """
  37. 初始化配置服务缓存
  38. 在数据库完全准备好后调用,预热配置缓存
  39. """
  40. try:
  41. with app.app_context():
  42. from app.services.config_service import config_service
  43. # 强制刷新配置缓存,预热缓存
  44. config_service._refresh_cache()
  45. print("配置服务缓存初始化完成")
  46. except Exception as e:
  47. print(f"配置服务缓存初始化失败: {e}")
  48. def create_app(test_config=None):
  49. """创建并配置Flask应用"""
  50. app = Flask(__name__, instance_relative_config=True)
  51. # 设置默认配置(先使用硬编码默认值)
  52. app.config.from_mapping(
  53. SECRET_KEY='dev',
  54. SQLALCHEMY_DATABASE_URI=f'sqlite:///{os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "financial_tools.db")}',
  55. SQLALCHEMY_TRACK_MODIFICATIONS=False,
  56. )
  57. # 加载配置文件
  58. if test_config is None:
  59. # 尝试从config.yaml加载配置
  60. config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'config.yaml')
  61. if os.path.exists(config_path):
  62. with open(config_path, 'r', encoding='utf-8') as f:
  63. config = yaml.safe_load(f)
  64. if config and 'flask' in config:
  65. app.config.update(config['flask'])
  66. else:
  67. # 使用测试配置
  68. app.config.from_mapping(test_config)
  69. # 确保data文件夹存在
  70. data_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'data')
  71. try:
  72. os.makedirs(data_path, exist_ok=True)
  73. except OSError:
  74. pass
  75. # 确保实例文件夹存在
  76. try:
  77. os.makedirs(app.instance_path)
  78. except OSError:
  79. pass
  80. # 初始化数据库
  81. init_db(app)
  82. # 数据库初始化完成后,尝试从配置服务更新Flask配置
  83. _update_flask_config_from_service(app)
  84. # 初始化配置服务缓存
  85. _initialize_config_service(app)
  86. # 注册蓝图
  87. register_blueprints(app)
  88. # 初始化数据更新服务
  89. from app.services.data_update import init_data_update_service
  90. init_data_update_service(app)
  91. # 注册命令行命令
  92. register_commands(app)
  93. # 注册首页路由
  94. @app.route('/')
  95. def index():
  96. from flask import render_template
  97. return render_template('index.html')
  98. return app
  99. def register_blueprints(app):
  100. app.register_blueprint(future_info_bp)
  101. app.register_blueprint(transaction_bp)
  102. app.register_blueprint(trade_bp)
  103. app.register_blueprint(monitor_bp)
  104. app.register_blueprint(dimension_bp)
  105. def register_commands(app):
  106. """注册Flask命令行命令"""
  107. @app.cli.command('update-future-data')
  108. @click.option('--mode', '-m', type=click.Choice(['daily', 'info', 'both']), default='both',
  109. help='更新模式: daily=只更新future_daily表, info=只更新future_info表, both=两者都更新')
  110. def update_future_data(mode):
  111. """更新期货数据,包括future_daily和future_info表"""
  112. from app.models.future_info import FutureInfo, FutureDaily
  113. from app.services.data_scraper import FutureDataScraper
  114. click.echo(f"开始更新期货数据,模式: {mode}")
  115. scraper = FutureDataScraper()
  116. if mode in ['daily', 'both']:
  117. # 更新future_daily表
  118. click.echo("正在更新future_daily表...")
  119. records_count = scraper.update_future_daily(db.session, FutureDaily)
  120. click.echo(f"future_daily表更新完成,共{records_count}条记录")
  121. if mode in ['info', 'both']:
  122. if mode == 'both':
  123. # 根据future_daily表更新future_info表
  124. click.echo("正在根据future_daily表更新future_info表...")
  125. updated_count = scraper.update_future_info_from_daily(db.session, FutureInfo, FutureDaily)
  126. else:
  127. # 直接从网站更新future_info表
  128. click.echo("正在直接从网站更新future_info表...")
  129. updated_count = scraper.update_future_info(db.session, FutureInfo)
  130. click.echo(f"future_info表更新完成,共更新{updated_count}条记录")
  131. click.echo("期货数据更新任务完成")
  132. @app.cli.command('init-trend-info')
  133. @click.option('--force', '-f', is_flag=True, help='强制重新初始化,清空现有数据')
  134. def init_trend_info_cmd(force):
  135. """初始化trend_info表数据,从config/trend_list.csv导入"""
  136. from app.models.dimension import TrendInfo
  137. from app.database.init_trend_info import init_trend_info
  138. if force:
  139. # 如果强制初始化,先清空现有数据
  140. click.echo("正在清空trend_info表...")
  141. db.session.query(TrendInfo).delete()
  142. db.session.commit()
  143. click.echo("trend_info表已清空")
  144. # 初始化trend_info表
  145. click.echo("正在初始化trend_info表...")
  146. init_trend_info()
  147. count = db.session.query(TrendInfo).count()
  148. click.echo(f"trend_info表初始化完成,共{count}条记录")
  149. @app.cli.command('init-candle-info')
  150. @click.option('--force', '-f', is_flag=True, help='强制重新初始化,清空现有数据')
  151. def init_candle_info_cmd(force):
  152. """初始化candle_info表数据,从config/candle_info.csv导入"""
  153. from app.models.dimension import CandleInfo
  154. from app.database.init_trend_info import init_candle_info
  155. if force:
  156. # 如果强制初始化,先清空现有数据
  157. click.echo("正在清空candle_info表...")
  158. db.session.query(CandleInfo).delete()
  159. db.session.commit()
  160. click.echo("candle_info表已清空")
  161. # 初始化candle_info表
  162. click.echo("正在初始化candle_info表...")
  163. init_candle_info()
  164. count = db.session.query(CandleInfo).count()
  165. click.echo(f"candle_info表初始化完成,共{count}条记录")