Flask配置MySQL连接信息的最佳实践

Flask连接MySQL的配置信息写在配置文件中的方法和最佳实践

在Flask项目中,将MySQL数据库连接信息写入配置文件是一种重要的工程实践,能够提高代码的可维护性、安全性和灵活性。下面详细介绍配置方法、不同配置方式的对比以及最佳实践。

一、配置MySQL连接信息的基本方法

1.1 直接在Flask应用中进行配置

最基本的配置方式是在Flask应用实例中直接设置数据库连接URI:

python 复制代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# 直接配置MySQL连接信息
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://username:password@localhost:3306/dbname'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

这种方式简单直接,但存在安全隐患,因为数据库密码等敏感信息直接暴露在代码中。

1.2 使用环境变量配置

为了避免敏感信息泄露,推荐使用环境变量来配置数据库连接信息:

python 复制代码
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# 从环境变量读取配置
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'mysql+pymysql://username:password@localhost:3306/dbname')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

在系统环境中设置环境变量:

bash 复制代码
export DATABASE_URL="mysql+pymysql://username:password@localhost:3306/dbname"

这种方式提高了安全性,敏感信息不会直接出现在代码版本控制中。

1.3 使用独立的配置文件

创建专门的配置文件(如config.py)来管理所有配置项:

config.py

python 复制代码
import os

class Config:
    """基础配置类"""
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard-to-guess-string'
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class DevelopmentConfig(Config):
    """开发环境配置"""
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \
        'mysql+pymysql://dev_user:dev_password@localhost:3306/dev_db'

class ProductionConfig(Config):
    """生产环境配置"""
    DEBUG = False
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'mysql+pymysql://prod_user:prod_password@localhost:3306/prod_db'

class TestingConfig(Config):
    """测试环境配置"""
    TESTING = True
    SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \
        'mysql+pymysql://test_user:test_password@localhost:3306/test_db'

config = {
    'development': DevelopmentConfig,
    'production': ProductionConfig,
    'testing': TestingConfig,
    'default': DevelopmentConfig
}

app.py

python 复制代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import config

db = SQLAlchemy()

def create_app(config_name='default'):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    
    db.init_app(app)
    
    return app

这种方式支持多环境配置,便于在不同部署环境中切换。

二、不同配置方式的对比分析

配置方式 安全性 维护性 灵活性 适用场景
直接配置 低 低 低 快速原型、学习演示
环境变量 高 中 中 生产环境、容器化部署
配置文件 中 高 高 复杂项目、多环境部署

三、完整的配置文件示例

下面是一个完整的Flask项目配置文件示例,展示了MySQL连接配置的最佳实践:

config.py

python 复制代码
import os
from datetime import timedelta

basedir = os.path.abspath(os.path.dirname(__file__))

class Config:
    """基础配置类"""
    # 安全配置
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'your-secret-key-here'
    
    # 数据库基础配置
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SQLALCHEMY_ECHO = False  # 是否打印SQL语句,开发时可设为True
    
    # 会话配置
    PERMANENT_SESSION_LIFETIME = timedelta(days=7)
    
    # 文件上传配置
    MAX_CONTENT_LENGTH = 16 * 1024 * 1024  # 16MB
    UPLOAD_FOLDER = os.path.join(basedir, 'uploads')
    
    @staticmethod
    def init_app(app):
        pass

class DevelopmentConfig(Config):
    """开发环境配置"""
    DEBUG = True
    # MySQL连接配置
    SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \
        'mysql+pymysql://dev_user:password@localhost:3306/flask_dev'
    # 开发环境下显示SQL语句
    SQLALCHEMY_ECHO = True

class ProductionConfig(Config):
    """生产环境配置"""
    DEBUG = False
    # 生产环境必须使用环境变量
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
    
    @classmethod
    def init_app(cls, app):
        Config.init_app(app)
        
        # 生产环境日志配置
        import logging
        from logging.handlers import RotatingFileHandler
        
        # 文件日志处理器
        file_handler = RotatingFileHandler(
            'logs/flask_app.log', 
            maxBytes=10485760,  # 10MB
            backupCount=10
        )
        file_handler.setLevel(logging.INFO)
        formatter = logging.Formatter(
            '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
        )
        file_handler.setFormatter(formatter)
        app.logger.addHandler(file_handler)

class TestingConfig(Config):
    """测试环境配置"""
    TESTING = True
    # 测试数据库配置
    SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \
        'mysql+pymysql://test_user:password@localhost:3306/flask_test'
    # 测试时禁用CSRF保护
    WTF_CSRF_ENABLED = False

# 配置字典
config = {
    'development': DevelopmentConfig,
    'production': ProductionConfig,
    'testing': TestingConfig,
    'default': DevelopmentConfig
}

四、数据库模型定义与使用

配置完成后,可以定义数据模型并使用数据库:

models.py

python 复制代码
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

db = SQLAlchemy()

class User(db.Model):
    """用户模型"""
    __tablename__ = 'users'
    
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True, nullable=False)
    email = db.Column(db.String(120), unique=True, index=True, nullable=False)
    password_hash = db.Column(db.String(128))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    def __repr__(self):
        return f'<User {self.username}>'

class Post(db.Model):
    """文章模型"""
    __tablename__ = 'posts'
    
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(140), nullable=False)
    content = db.Column(db.Text)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # 关系定义
    author = db.relationship('User', backref=db.backref('posts', lazy='dynamic'))
    
    def __repr__(self):
        return f'<Post {self.title}>'

app.py

python 复制代码
from flask import Flask
from config import config
from models import db

def create_app(config_name='default'):
    app = Flask(__name__)
    
    # 加载配置
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)
    
    # 初始化扩展
    db.init_app(app)
    
    # 注册蓝图
    from auth import auth_bp
    from main import main_bp
    
    app.register_blueprint(auth_bp)
    app.register_blueprint(main_bp)
    
    return app

# 应用工厂的使用
app = create_app('development')

@app.shell_context_processor
def make_shell_context():
    """为Flask shell添加上下文"""
    return {'db': db, 'User': User, 'Post': Post}

if __name__ == '__main__':
    app.run()

五、数据库迁移配置

对于生产环境,数据库迁移是必不可少的。配置Flask-Migrate:

migrate.py

python 复制代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from config import config

db = SQLAlchemy()
migrate = Migrate()

def create_app(config_name='default'):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    
    db.init_app(app)
    migrate.init_app(app, db)
    
    return app

使用迁移命令:

bash 复制代码
# 初始化迁移仓库
flask db init

# 生成迁移脚本
flask db migrate -m "Initial migration"

# 应用迁移
flask db upgrade

六、最佳实践总结

1

相关推荐
默_笙4 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
qq_426003964 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
虎头金猫4 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
长沙三为智能科技4 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python
小白男神4 天前
MySQL进阶学习四(存储过程、游标、触发器)
mysql
伞伞悦读4 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
这个DBA有点耶4 天前
MVCC深入:Read View、版本链与快照读——InnoDB并发控制的内核
数据库·mysql·架构
只睡四小时4 天前
Canvas 弹道联机实战:700 行 + 固定时间步长
python·websocket·html5·游戏开发·canvas
奇思妙想聪明勤奋的小羊4 天前
DeepAgents第5章:子Agent 与上下文隔离—让 Agent学会委派
人工智能·python·学习·语言模型
lpfasd1234 天前
2026年第38周GitHub趋势周报
python·科技·github