python 无法使用flask.g访问其他函数中的变量

i2loujxw  于 2023-05-27  发布在  Python
关注(0)|答案(4)|浏览(153)

我试图使用flask.g来存储可以在其他函数中访问的变量,但我似乎没有正确地执行某些操作。当我尝试访问g.name时,应用程序生成以下错误:AttributeError: '_RequestGlobals' object has no attribute 'name'
flask.g的文档说:
把你想要的东西都放在这上面。例如数据库连接或当前登录的用户。
下面是一个完整的、最小的示例,它说明了当我试图在创建变量的函数之外访问变量时收到的错误。任何帮助将不胜感激。

#!/usr/bin/env python

from flask import Flask, render_template_string, request, redirect, url_for, g
from wtforms import Form, TextField

application = app = Flask('wsgi')

@app.route('/', methods=['GET', 'POST'])
def index():
    form = LoginForm(request.form)

    if request.method == 'POST' and form.validate():
        name =  form.name.data
        g.name = name

        # Need to create an instance of a class and access that in another route
        #g.api = CustomApi(name)

        return redirect(url_for('get_posts'))

    else:

        return render_template_string(template_form, form=form)

@app.route('/posts', methods=['GET'])
def get_posts():
    # Need to access the instance of CustomApi here
    #api = g.api
    name = g.name
    return render_template_string(name_template, name=name)

class LoginForm(Form):
    name = TextField('Name')

template_form = """
{% block content %}
<h1>Enter your name</h1>

<form method="POST" action="/">
    <div>{{ form.name.label }} {{ form.name() }}</div><br>
    <button type="submit" class="btn">Submit</button>    
</form>
{% endblock %}

"""

name_template = """
{% block content %}

    <div>"Hello {{ name }}"</div><br>

{% endblock %}

"""

if __name__ == '__main__':
    app.run(debug=True)
dbf7pr2w

dbf7pr2w1#

g对象是一个基于请求的对象,在请求之间不持久,即g在您对index的请求和对get_posts的请求之间重新创建。
Flask中的应用程序全局变量:
Flask为您提供了一个特殊的对象,确保它仅对活动请求有效,并且将为每个请求返回不同的值。简而言之:它会做正确的事情,就像它对请求和会话所做的那样。
对于请求之间的微小数据的持久存储,请使用sessions。如果您有充分的理由这样做,您可以(但不应该)将数据直接存储在app对象中用于全局(所有会话)应用程序状态,类似于config所做的。
对于更复杂的数据,使用数据库。

zrfyljdw

zrfyljdw2#

如果您需要跟踪身份验证信息,我建议使用Flask插件之一,如Flask-LoginFlask-Principal
例如,我们使用Flask-Principal。当有人进行身份验证(或者检测到身份验证cookie)时,它会发出身份加载信号。然后,我们将他们的登录身份与数据库中的用户进行Map。就像这样:

# not actual code
@identity_loaded.connect_via(app)
def on_identity_loaded(sender, identity):
  user = Person.query.filter(Person.username==identity.person.username).one()
  g.user = user

然后我们可以在任何控制器或模板中使用g.user。(我们实际上正在删除很多内容,这是一个简单的,懒惰的黑客,造成了比它更大的麻烦。
如果你不想使用模块,有一个内置的信号,你可以在每个请求开始时挂钩:
http://flask.pocoo.org/docs/tutorial/dbcon/

# This runs before every request
@app.before_request
def before_request():
    g.user = your_magic_user_function()

并且G.user将在任何地方神奇地可用。
我希望这有帮助!

xdnvmnnf

xdnvmnnf3#

只需在 flask 中使用会话。在您的情况下,您只想保存请求中的用户/名称,最简单的方法是使用会话。

from flask import session
app.secret_key = 'some key for session'

然后,您的功能可以更改如下:

@app.route('/', methods=['GET', 'POST'])
def index():
    form = LoginForm(request.form)
    if request.method == 'POST' and form.validate():
        session['name'] =  form.name.data
        return redirect(url_for('get_posts'))
    else:
        return render_template_string(template_form, form=form)

@app.route('/posts', methods=['GET'])
def get_posts():
    if 'name' in session:
        name = session['name']
    else:
        name = "Unknown"
    return render_template_string(name_template, name=name)
kmb7vmvb

kmb7vmvb4#

我想更详细地介绍一下g global在存储数据方面的使用。g仅存储请求的生命周期内的数据以及任何后续重定向到另一个路由的数据。之后,g全局设置回null。这意味着在一个请求中在g中设置的任何内容都不能在另一个请求中访问。使用会话来存储将跨请求访问的数据。
使用g global的一个好处是在连接到数据库以获取用户时。例如,可以是来自数据库的管理员。可以使用以下方法将admin存储在g全局中。

from flask import Flask, g
app = Flask(__name__)

@app.before_request
def text():
    g.a = User.query.filter_by(email='admin@gmail.com')
    

@app.route("/getTrue", methods=['GET', 'POST'])
def getTrue():
    form = UserForm()
    if form.validate_on_submit():
        if g.a == form.email.data:
              return "Admin is logged in"
        else:
              return "User is logged in"
    return render_template('login.html', form=form)

在上面的示例中,g可以用于保存将在另一个请求中使用的数据。我希望这对你有帮助,谢谢。

相关问题