首页 > 解决方案 > Flask,管理数据库连接(无 ORM)

问题描述

总的来说,我是 Flask 和网络编程的新手,所以我试图了解框架的上下文和数据库操作的原理。现在我想弄清楚如何在没有 Sql-Alchemy 和其他 ORM 的情况下管理数据库连接,只需使用普通 sql。

所以使用 sqlite3 db 的简单示例。我的测试项目的结构:

.
├── application
│   ├── __init__.py
│   ├── routes.py
│   └── templates
│       ├── base.html
│       ├── index.html
├── config.py
├── requirements.txt
├── run.py
└── test.db

初始化.py

from flask import Flask,g
from config import Config
import sqlite3

app = Flask(__name__)
app.config.from_object(Config)


def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = sqlite3.connect('test.db')
    return db

@app.teardown_appcontext
def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.close()

from application import routes

路线.py

# -*- coding: utf-8 -*-
from flask import render_template,redirect
from application import app, get_db
# import sqlite3


@app.route('/')
def index():
    cur = get_db().cursor()
    cur.execute('select*from users')
    select=cur.fetchall()
    return render_template('index.html',title='DBSelectTest', posts=select)

我已经从 Flask 框架的官方站点复制了“get_db”和“close_connection”函数,但是我不清楚它是如何工作的,如果我只对“def get_db”使用没有“g”的简单代码会有什么区别“ 像这样:

con = sqlite3.connect("catalog.db")
cur = con.cursor() 

并且显然在查询完成后关闭连接是这样的:

cur.close()    
con.close() 

我只是想通过使用 g 来了解应用程序和请求上下文在这种情况下是如何工作的。在这种情况下,我不明白什么是“请求”的主要问题。

我对这个案例的错误理解:

因此,在init .py 中,我们创建了“全局变量”g,它位于应用程序上下文中,并且应该可以被请求上下文中的每个踏板访问。在 routes.py 中,我们使用 root route("/") 从客户端获取查询,因此在那一刻创建了请求上下文,并且在该应用程序上下文之后也是如此。因此,据我了解,“get_db”可以从我们的请求上下文中访问,并且我们能够连接到数据库并在当前胎面内的所有函数中使用该 g 值?那么“close_connection”呢?由于装饰器“teardown_appcontext”,连接必须在应用上下文失败或结束后关闭?它会在我的代码中工作吗?

那么,任何人都可以提供使用带有单独连接功能的普通 sql 的正确案例吗?

标签: flask

解决方案


Flask 应用程序和请求上下文在您的代码中表现得像全局变量,但实际上是代理,每次您的应用程序收到新的 Web 请求时都会包含不同的值。请求上下文包含特定于该特定 Web 请求的数据,例如表单数据、远程 IP 地址、http 标头等。

每次收到 Web 请求时,都会在调用视图函数之前创建新的应用程序和请求上下文,然后在返回响应并完成 Web 请求的处理后销毁这些上下文。代理与应用程序上下文一起存储,g它用于存储具有特定 Web 请求生命周期的变量。这用于在flask调用的函数之间传递信息,作为事件和信号的结果。

在您的代码中,您使用装饰器将函数注册到close_connection事件teardown_appcontext中,从而保证在完成每个 Web 请求的处理后调用它。还有许多其他事件可以在视图函数之前或之后执行,以提供请求或响应的预处理和后处理。代理仅用于存储在视图函数中创建的g数据库连接,并使其可用于close_connection保证关闭的函数。如果您的应用程序代码中发生错误,这可以防止数据库连接保持打开状态。

如下所示,该模式用于完成与使用上下文管理器(或 try、except、finally 块)关闭函数中的数据库连接所实现的完全相同的事情。这种模式通常与 ORM 一起使用,以隐藏数据库连接的底层管理并减少样板代码。以下代码在不使用事件或 g 代理的情况下应该产生相同的效果。

# -*- coding: utf-8 -*-
from flask import render_template, redirect
from application import app
from contextlib import closing
import sqlite3

def get_db():
    return sqlite3.connect('test.db')

@app.route('/')
def index():
    with closing(get_db()) as conn:
        cur = conn.cursor()
        cur.execute('select * from users')
        select = cur.fetchall()
    return render_template('index.html', title='DBSelectTest', posts=select)

推荐阅读