1

我正在开发一个需要使用最终用户提供的凭据登录数据库的 Web 应用程序;应用程序本身没有登录数据库。

问题是如何为每个用户会话创建一个连接

一种方法是:

  1. 请求用户的凭据
  2. 检查凭据是否对 db 后端有效
  3. 将凭据存储在会话级变量中

这种方法的问题在于,对于该会话的每个后续请求;您需要创建一个新连接;这将很快耗尽与服务器的最大连接。

我正在将Flask与 Oracle 一起使用。

在 Flask 中有一个g对象,它存储请求范围的对象。但是,此代码段不起作用:

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

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if g.db is None:
            return redirect(url_for('login', next=request.url))
        return f(*args, **kwargs)
     return decorated_function

class LoginForm(Form):
    username = TextField('Username', [validators.Length(min=4, max=25)])
    password = PasswordField('Password', [validators.Required()])

@app.route('/app', methods=['GET','POST'])
@login_required
def index():
    return 'Index'

@app.route('/', methods=['GET','POST'])
def login():
    form = LoginForm(request.form)
    if request.method == 'POST':
        if form.validate():
           try:
               dsn = cx_Oracle.makedsn(app.config['DB_HOST'],
                                       app.config['DB_PORT'], app.config['DB_SID'])
               g.db = cx_Oracle.connect(form.username.data,
                                        form.password.data, dsn)
           except cx_Oracle.DatabaseError as e:
               flash(unicode(e), 'error')
               return render_template('login.html', form=form)
            return redirect(url_for('index'))
        else:
            return render_template('login.html', form=form)
    else:
        return render_template('login.html', form=form)

AttributeError: '_RequestGlobals' object has no attribute 'db'

4

2 回答 2

1

此代码段不起作用的原因是这一行

    if g.db is None:

您正在访问不属于 g 的属性。添加这些代码行:

    @app.before_request
    def before_request():
         g.db = None

标有 before_request() 的函数在请求之前调用并且不传递任何参数。

关于连接池

Python 中有一个名为SQLAlchemy的 ORM 和 SQL 工具包,它会自动为您执行连接池。它还管理烧瓶的 g 对象并创建更安全的准备好的 SQL 语句。

它有两个部分:

    1. Core which is a SQL abstraction toolkit.
    2. ORM is an optional package which builds on top of Core.

因此,如果您不想使用 ORM,那么只需使用其所有功能完整的核心即可。在这里检查。

它通过 cx_Oracle 支持 Oracle,并且可以按照这里的 SQLAlchemy Docs 中所述进行设置。

检查此问题以获取有关 python 中的连接池的更多讨论。

于 2012-06-08T09:08:35.820 回答
0

Sounds like you need to implement connection pooling. Instead of requesting a new connection for each request (which does not scale at all), you simply check out a connection from the pool with the required attributes. If no suitable connection is available, the pool would create a new one. The pool would also need to handle the opposite case of course in closing connections that haven't been used for some time.

You might want to check if such a pool is available for python. For java oracle supports this with UCP and for OCI with the session pool. If I'm not mistaken a connection pool is even provided for .Net.

于 2012-06-08T02:09:33.943 回答