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

相关推荐
一晌小贪欢32 分钟前
Python基础:第 09 篇 · while 循环:重复直到不满足
开发语言·c++·python·数据可视化·面向对象·python办公
一条大祥脚1 小时前
CuTe 与 CuTe DSL:从 C++ 模板元编程到 Python DSL 的 GPU 编程演进
开发语言·c++·python·cutlass·cute·cute dsl
10年前端老司机2 小时前
Milvus 8种检索能力实践
数据库·python·agent
aiks_yuan2 小时前
MySQL 深分页 LIMIT 越翻越慢怎么办:300 万行实测 OFFSET、延迟关联和 keyset 的耗时差距(MySQL 8.2)
mysql
Decay__2 小时前
14_MySQL 高可用与容灾架构 —— MGR / InnoDB Cluster / Keepalived+VIP / 双主 / 读写分离 / 两地三中心
运维·数据库·sql·mysql·架构
Sakura_j_h_3 小时前
从零写一个 MCP stdio Server:用 Python 校验博客文章格式
开发语言·python·自动化·ai工具·mcp·json-rpc
大草原的小灰灰3 小时前
LLM应用的标准开发框架LangChain(八)- 中间件
python·中间件·langchain
卷无止境3 小时前
百万 token 时代的真相:主流大模型上下文窗口与最大输出的横向对比分析
人工智能·python
用户298698530143 小时前
Python 实战:将 HTML 批量转换为 Markdown
python·html·markdown
hhcgchpspk4 小时前
flask服务端页面预防被爬措施
后端·python·flask·网络爬虫·防爬