/
app.py
321 lines (276 loc) · 8.17 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
import os
from settings import Env, config
from flask import Flask as BasicFlask, current_app
from flask_wtf.csrf import CSRFError
from utils import is_empty, render_info, MyResponse
from views import demo_bp
from views.ai import img_bp, audio_bp
from views.sys import user_bp, area_bp, menu_bp, dict_bp, file_bp
from views.api import img_api_bp, ocr_api_bp
from extensions import db, moment, migrate, init_log, scheduler, cache, login_manager, session, csrf, JSONEncoder
from utils.request import codes
from models.audio import AudioLexerNeModel
class Flask(BasicFlask):
def get_object_dict(self, o_key):
"""
根据对象名查询配置参数信息
:param o_key:
:return:
"""
return self.config.get('OBJECT_DICT', {}).get(o_key, {})
def create_app(config_name=None):
"""
工厂函数
:param config_name:
:return:
"""
if is_empty(config_name) or config_name not in [env.value for env in Env]:
config_name = os.getenv('FLASK_CONFIG', Env.DEVELOPMENT.value)
app = Flask(import_name=__name__)
# 加载配置
app.config.from_object(obj=config[config_name])
# 注册JSON解析器
app.json_encoder = JSONEncoder
# 注册日志
app.logger.addHandler(init_log(app.config.get('PROJECT_NAME', None), app.config.get('LOGGER_LEVER', None)))
# 注册扩展
register_extensions(app)
# 注册蓝本
register_blueprints(app)
# 注册错误处理函数
register_errors(app)
# 注册shell上下文处理函数
register_shell_context(app)
# 注册模板上下文处理函数
register_template_context(app)
# 注册模板过滤器
register_template_filter(app)
# 注册模板测试器
register_template_test(app)
return app
def register_blueprints(app):
"""
蓝本初始化
:param app:
:return:
"""
app.register_blueprint(blueprint=area_bp, url_prefix='/sys')
app.register_blueprint(blueprint=user_bp, url_prefix='/sys/user')
app.register_blueprint(blueprint=menu_bp, url_prefix='/sys/menu')
app.register_blueprint(blueprint=dict_bp, url_prefix='/sys/dict')
app.register_blueprint(blueprint=file_bp, url_prefix='/sys/file')
app.register_blueprint(blueprint=img_bp, url_prefix='/ai/img')
app.register_blueprint(blueprint=audio_bp, url_prefix='/audio')
app.register_blueprint(blueprint=demo_bp, url_prefix='/demo')
app.register_blueprint(blueprint=img_api_bp, url_prefix='/api/img')
app.register_blueprint(blueprint=ocr_api_bp, url_prefix='/api/ocr')
def register_extensions(app):
"""
扩展实例化
:param app:
:return:
"""
db.init_app(app)
moment.init_app(app)
migrate.init_app(app=app, db=db)
cache.init_app(app)
login_manager.init_app(app)
# 登录过滤保护
login_manager.exempt_views((user_bp, demo_bp, audio_bp, img_api_bp, ocr_api_bp))
session.init_app(app)
csrf.init_app(app)
# csrf过滤保护
csrf.exempt_views((demo_bp, audio_bp, img_api_bp, ocr_api_bp))
# 定时任务 解决FLASK DEBUG模式定时任务执行两次
if os.environ.get('FLASK_DEBUG', '0') == '0':
scheduler.init_app(app)
scheduler.start()
elif os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
scheduler.init_app(app)
scheduler.start()
def register_errors(app):
"""
错误函数初始化
:param app:
:return:
"""
@app.errorhandler(codes.bad)
def bad_request(e):
"""
400
:param e:
:return:
"""
return render_info(
info=MyResponse(
code=codes.bad,
msg='无效的请求'
),
template='errors/400.html',
status=codes.bad
)
@app.errorhandler(codes.not_found)
def page_not_found(e):
"""
404
:param e:
:return:
"""
return render_info(
info=MyResponse(
code=codes.not_found,
msg='资源不存在'
),
template='errors/404.html',
status=codes.not_found
)
@app.errorhandler(codes.not_allowed)
def not_allowed(e):
"""
405
:param e:
:return:
"""
return render_info(
info=MyResponse(
code=codes.not_allowed,
msg='无效的请求头或方法'
),
template='errors/405.html',
status=codes.not_allowed
)
@app.errorhandler(CSRFError)
def handle_csrf_error(e):
"""
CSRF验证失败
:param e:
:return:
"""
return render_info(
info=MyResponse(
code=codes.bad,
msg=e.description if e.description else repr(e)
),
template='errors/400.html',
status=codes.bad
)
@app.errorhandler(codes.unprocessable)
def handle_validation_error(e):
"""
422 参数校验错误
:param e:
:return:
"""
return render_info(
info=MyResponse(
code=codes.unprocessable,
msg=e.exc.messages if e.exc else repr(e)
),
template='errors/422.html',
status=codes.unprocessable
)
@app.errorhandler(Exception)
def handle_unknown_error(e):
"""
未知的异常
:param e:
:return:
"""
try:
return render_info(info=MyResponse.init_error(e), template='errors/500.html')
finally:
# 记录日志
current_app.logger.exception(e)
def register_shell_context(app):
"""
shell上下文初始化
:param app:
:return:
"""
pass
def register_template_context(app):
"""
模板上下文初始化
:param app:
:return:
"""
pass
def register_template_filter(app):
"""
自定义过滤器
:param app:
:return:
"""
@app.template_filter('filter_none')
def filter_none(v):
"""
空值过滤
:param v:
:return:
"""
return '' if v is None else v
@app.template_filter('ms_to_time')
def ms_to_time(ms):
"""
毫秒转时间格式
:param ms:
:return:
"""
from utils import ms_to_time as ms_to_time_util
return ms_to_time_util(ms)
@app.template_filter('lexer_label')
def lexer_label(text, asr_nlp_data):
"""
语义标签过滤
:param str text:
:param asr_nlp_data:
:return:
"""
_item = '<font id="{id}" class="{ne} lexer_font_show" color="{color}" ' \
'data-ne-title="{ne_title}" data-bg="{bg}" data-ed="{ed}" ' \
'data-onebest="{onebest}" data-speaker="{speaker}">{item}</font>'
_ne_key = 'ne_{0}'
if is_empty(asr_nlp_data) or is_empty(asr_nlp_data.items):
return text
ne_dict = {}
for item in asr_nlp_data.items:
lexer = AudioLexerNeModel().dao_get_by_code(item.ne) # type: AudioLexerNeModel
ne_key = '{' + _ne_key.format(str(item.byte_offset)) + '}'
text = text.replace(item.item, ne_key, 1)
ne_dict.update(
{_ne_key.format(str(item.byte_offset)): _item.format(
id=item.id,
ne=item.ne,
color=lexer.color,
ne_title=lexer.title,
item=item.item,
bg=asr_nlp_data.bg,
ed=asr_nlp_data.ed,
onebest=asr_nlp_data.onebest,
speaker=asr_nlp_data.speaker
)}
)
return text.format_map(ne_dict)
def register_template_test(app):
"""
自定义测试器
:param app:
:return:
"""
@app.template_test(name='odd')
def odd(n):
"""
判断是否为基数
:param int n:
:return:
"""
from utils import is_odd
return is_odd(n)
@app.template_test(name='empty')
def empty(o):
"""
判断是否为空
:param o:
:return:
"""
return True if is_empty(o) else False