Flask-SQLAlchemy 初始化源码和蓝图blueprint源码小分析

本文详细分析了Flask-SQLAlchemy库中初始化过程,包括如何通过`init_app`方法设置数据库配置,并将实例添加到`extensions`字典。同时,探讨了蓝图(Blueprint)的创建、注册及路由装饰器的工作原理,解释了蓝图如何在应用中组织和管理视图函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. Flask-SQLAlchemy 初始化源码

在文件中定义了工厂函数 create_app :

def create_app(config):
    """ 可以根据传入的 config 名称,加载不同的配置
    """

    app = Flask(__name__)
    app.config.from_object(configs.get(config))
    # SQLAlchemy 的初始化方式改为使用 init_app
    db.init_app(app)

如上所示的最后一行代码,db 对象一般是在models.py 文件中定义的 SQLAlchemy 类的实例,db = SQLAlchemy()。这里将应用对象作为参数调用实例的 init_app 方法进行初始化。

到现在为止我们只知道初始化,但并不知道实际发生了什么。

我们看下 SQLAlchemy 这个类的源码,首先它是来自 flask_sqlalchemy.__init__ 模块中:

cd /usr/local/lib/python3.8/dist-packages/flask_sqlalchemy
sudo vim __init__.py
class SQLAlchemy(object):
    """This class is used to control the SQLAlchemy integration to one
    or more Flask applications.  Depending on how you initialize the
    object it is usable right away or will attach as needed to a
    Flask application.

    There are two usage modes which work very similarly.  One is binding
    the instance to a very specific Flask application::

        app = Flask(__name__)
        db = SQLAlchemy(app)

因为在创建该类的实例的时候,没有提供参数,我们就直接看 init_app 方法的源码:

在这里插入图片描述
如上图所示,init_app 方法只需要提供一个 app 参数,也就是应用对象。

在第 847 行有一个判断,要求 app.config 这个类字典对象中必须要有 SQLALCHEMY_DATABASE_URI 或者 SQLALCHEMY_BINDS 这两个配置项中的一个,不然就会抛出一个警告信息:默认使用 SQLite3

<think>我们使用Flask蓝图来组织一个用户登录的程序。这里将创建几个文件: 1. `app.py` - 主应用文件 2. `auth/__init__.py` - 蓝图的包初始化文件(可以空着) 3. `auth/views.py` - 包含认证相关的视图(登录、登出等) 4. `templates/auth/login.html` - 登录页面模板 注意:为了简化,我们使用内存中的字典模拟用户数据库,并且不涉及密码加密(实际应用中必须加密存储密码)。 步骤: 1. 创建Flask应用实例。 2. 创建并注册蓝图。 3. 在蓝图中定义登录视图。 4. 使用会话(session)来管理用户登录状态。 文件结构: ``` project/ app.py auth/ __init__.py views.py templates/ auth/ login.html ``` 首先,我们创建`app.py`:</think>下面是一个使用Flask蓝图(Blueprint)实现的用户登录系统,包含完整源码详细解释: ### 文件结构 ``` myapp/ ├── app.py # 主应用文件 ├── auth/ # 认证蓝图 │ ├── __init__.py # 蓝图初始化 │ ├── routes.py # 认证路由 │ └── templates/ # 蓝图专属模板 │ └── auth/ # 模板目录 │ ├── login.html │ └── profile.html └── templates/ # 全局模板 └── base.html # 基础模板 ``` ### 源码实现 1. **主应用文件 (app.py)**: ```python from flask import Flask from auth.routes import auth_bp app = Flask(__name__) app.secret_key = 'your_secret_key_here' # 用于会话安全 # 注册蓝图 app.register_blueprint(auth_bp, url_prefix='/auth') if __name__ == '__main__': app.run(debug=True) ``` 2. **蓝图初始化 (auth/__init__.py)**: ```python from flask import Blueprint # 创建名为'auth'的蓝图,模板目录为'auth/templates' auth_bp = Blueprint('auth', __name__, template_folder='templates') # 导入路由(避免循环导入) from . import routes ``` 3. **认证路由 (auth/routes.py)**: ```python from flask import render_template, redirect, url_for, flash, request, session from . import auth_bp # 模拟用户数据库 USERS = { 'user1': {'password': 'pass1', 'name': 'User One'}, 'user2': {'password': 'pass2', 'name': 'User Two'} } @auth_bp.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') # 验证用户 if username in USERS and USERS[username]['password'] == password: session['user'] = username # 创建会话 flash('登录成功!', 'success') return redirect(url_for('auth.profile')) else: flash('用户名或密码错误', 'danger') return render_template('auth/login.html') @auth_bp.route('/profile') def profile(): if 'user' not in session: flash('请先登录', 'warning') return redirect(url_for('auth.login')) user_data = USERS.get(session['user']) return render_template('auth/profile.html', user=user_data) @auth_bp.route('/logout') def logout(): session.pop('user', None) # 销毁会话 flash('您已成功登出', 'info') return redirect(url_for('auth.login')) ``` 4. **基础模板 (templates/base.html)**: ```html <!DOCTYPE html> <html> <head> <title>{% block title %}{% endblock %} - Flask登录系统</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> </head> <body> <div class="container mt-5"> <!-- 闪现消息 --> {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %} <div class="alert alert-{{ category }} alert-dismissible fade show"> {{ message }} <button type="button" class="close" data-dismiss="alert">×</button> </div> {% endfor %} {% endif %} {% endwith %} <!-- 内容块 --> {% block content %}{% endblock %} </div> </body> </html> ``` 5. **登录页面 (auth/templates/auth/login.html)**: ```html {% extends "base.html" %} {% block title %}登录{% endblock %} {% block content %} <div class="row justify-content-center"> <div class="col-md-6"> <h2 class="mb-4">用户登录</h2> <form method="POST"> <div class="form-group"> <label for="username">用户名</label> <input type="text" class="form-control" id="username" name="username" required> </div> <div class="form-group"> <label for="password">密码</label> <input type="password" class="form-control" id="password" name="password" required> </div> <button type="submit" class="btn btn-primary btn-block">登录</button> </form> </div> </div> {% endblock %} ``` 6. **个人资料页 (auth/templates/auth/profile.html)**: ```html {% extends "base.html" %} {% block title %}个人资料{% endblock %} {% block content %} <div class="card"> <div class="card-header"> <h4>用户资料</h4> </div> <div class="card-body"> <p><strong>用户名:</strong> {{ user.name }}</p> <p><strong>登录ID:</strong> {{ session.user }}</p> <a href="{{ url_for('auth.logout') }}" class="btn btn-danger">登出</a> </div> </div> {% endblock %} ``` ### 关键功能解释 1. **蓝图结构**: - 使用`Blueprint`创建独立认证模块 - `url_prefix='/auth'`使所有路由以`/auth`开头 - 蓝图专属模板目录避免命名冲突 2. **会话管理**: - `session`存储用户登录状态 - `session['user'] = username` 登录时设置 - `session.pop('user')` 登出时清除 3. **安全机制**: - `app.secret_key` 用于签名会话cookie - 密码验证前检查用户是否存在(避免时序攻击) - 使用POST方法提交敏感数据 4. **用户体验**: - Flask的`flash`消息系统提供操作反馈 - 登录保护:未登录用户访问资料页自动跳转 - Bootstrap美化界面 ### 运行步骤 1. 创建上述文件结构 2. 安装依赖:`pip install flask` 3. 运行:`python app.py` 4. 访问: - 登录页:http://localhost:5000/auth/login - 测试账号:user1/pass1 或 user2/pass2 ### 功能扩展建议 - 添加用户注册功能 - 实现数据库持久化(SQLAlchemy- 增加密码加密(Flask-Bcrypt) - 添加"记住我"功能 - 实现权限分级控制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值