初始化技术博客项目
功能特性: - 前端文章展示 (Markdown渲染、代码高亮) - 后台管理系统 (文章、分类、标签、作者管理) - 图片上传 (点击、拖拽、粘贴) - 网站设置 (Logo、底部宣传图片上传) - 访问统计 (IP记录、趋势图表) - 参考来源、附件支持 - 单端口部署 (16012) 技术栈: - Flask 3.0 + SQLAlchemy - SQLite数据库 - marked.js + highlight.js (Markdown渲染) - Chart.js (统计图表)
This commit is contained in:
137
app/__init__.py
Normal file
137
app/__init__.py
Normal file
@@ -0,0 +1,137 @@
|
||||
"""Flask应用工厂"""
|
||||
from flask import Flask, g, request, send_from_directory
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_migrate import Migrate
|
||||
import os
|
||||
|
||||
db = SQLAlchemy()
|
||||
migrate = Migrate()
|
||||
|
||||
|
||||
def create_app(config_name='default'):
|
||||
"""创建Flask应用实例"""
|
||||
from app.config import config_map
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(config_map[config_name])
|
||||
|
||||
# 初始化扩展
|
||||
db.init_app(app)
|
||||
migrate.init_app(app, db)
|
||||
|
||||
# 确保数据目录和上传目录存在
|
||||
data_dir = os.path.join(app.root_path, '..', 'data')
|
||||
uploads_dir = os.path.join(app.root_path, '..', 'uploads')
|
||||
os.makedirs(data_dir, exist_ok=True)
|
||||
os.makedirs(uploads_dir, exist_ok=True)
|
||||
|
||||
# 配置上传目录
|
||||
app.config['UPLOAD_FOLDER'] = uploads_dir
|
||||
|
||||
# 注册蓝图
|
||||
from app.routes.frontend import frontend_bp
|
||||
from app.routes.admin import admin_bp
|
||||
|
||||
app.register_blueprint(frontend_bp)
|
||||
app.register_blueprint(admin_bp, url_prefix='/admin')
|
||||
|
||||
# 注册上传文件路由(在蓝图之前,确保全局可访问)
|
||||
@app.route('/uploads/<path:filename>')
|
||||
def serve_upload(filename):
|
||||
"""提供上传文件访问"""
|
||||
return send_from_directory(uploads_dir, filename)
|
||||
|
||||
# 注册模板过滤器
|
||||
register_filters(app)
|
||||
|
||||
# 注册命令
|
||||
register_commands(app)
|
||||
|
||||
# 注册请求钩子(访问统计和网站配置)
|
||||
register_hooks(app)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
def register_filters(app):
|
||||
"""注册自定义模板过滤器"""
|
||||
from datetime import datetime
|
||||
|
||||
@app.template_filter('datetime_format')
|
||||
def datetime_format(value, format='%Y-%m-%d %H:%M'):
|
||||
"""格式化日期时间"""
|
||||
if value is None:
|
||||
return ''
|
||||
return value.strftime(format)
|
||||
|
||||
@app.template_filter('truncate_content')
|
||||
def truncate_content(value, length=200):
|
||||
"""截断文章内容用于预览"""
|
||||
if len(value) <= length:
|
||||
return value
|
||||
return value[:length] + '...'
|
||||
|
||||
|
||||
def register_commands(app):
|
||||
"""注册自定义命令"""
|
||||
import click
|
||||
|
||||
@app.cli.command('init-db')
|
||||
def init_db():
|
||||
"""初始化数据库"""
|
||||
db.create_all()
|
||||
click.echo('数据库初始化完成。')
|
||||
|
||||
@app.cli.command('create-admin')
|
||||
@click.argument('username')
|
||||
@click.argument('password')
|
||||
def create_admin(username, password):
|
||||
"""创建管理员账户"""
|
||||
from app.models.admin import Admin
|
||||
from werkzeug.security import generate_password_hash
|
||||
|
||||
admin = Admin.query.filter_by(username=username).first()
|
||||
if admin:
|
||||
click.echo(f'管理员 {username} 已存在!')
|
||||
return
|
||||
|
||||
admin = Admin(
|
||||
username=username,
|
||||
password_hash=generate_password_hash(password)
|
||||
)
|
||||
db.session.add(admin)
|
||||
db.session.commit()
|
||||
click.echo(f'管理员 {username} 创建成功!')
|
||||
|
||||
|
||||
def register_hooks(app):
|
||||
"""注册请求钩子"""
|
||||
from app.services import SiteConfigService, VisitService
|
||||
|
||||
@app.before_request
|
||||
def before_request():
|
||||
"""请求前处理:注入网站配置"""
|
||||
# 获取网站配置并注入到g对象
|
||||
g.site_config = SiteConfigService.get_dict()
|
||||
|
||||
@app.after_request
|
||||
def after_request(response):
|
||||
"""请求后处理:记录访问日志"""
|
||||
# 只记录前端请求,不记录静态资源和后台
|
||||
if request.path.startswith('/static') or request.path.startswith('/admin'):
|
||||
return response
|
||||
|
||||
# 只记录成功的请求
|
||||
if response.status_code == 200:
|
||||
# 检查是否是文章详情页
|
||||
article_id = None
|
||||
if hasattr(g, 'current_article_id'):
|
||||
article_id = g.current_article_id
|
||||
|
||||
# 记录访问
|
||||
try:
|
||||
VisitService.log_visit(request, article_id)
|
||||
except Exception:
|
||||
pass # 忽略记录错误,不影响正常响应
|
||||
|
||||
return response
|
||||
Reference in New Issue
Block a user