Reputation: 1508
So I'm having issues with passing in a list from my Flask session object into the WTForms that I'm using. I'm trying to access the 'strategy' object (it's a list) within the session object.
The goal is to list all of the strategies that are associated with the current user.
Within the Flask app:
class Create_Indicator_Form(Form):
security = TextField('Ticker Name', [
validators.Required(),
validators.Length(min=1, max=6)])
mva_10 = BooleanField('10 day moving average')
mva_25 = BooleanField('25 day moving average')
strategy = SelectField('strategy', session['strategy'])
def validate_mva_10(form, field):
if form.mva_25.data is True and field.data is True:
raise ValidationError('You can only choose one reference')
if form.mva_25.data is False and field.data is False:
raise ValidationError('You must choose at least one reference')
@app.route('/create_indicator', methods=['GET', 'POST'])
def create_indicator():
check_if_logged_in()
f = request.form
create_indicator_form = Create_Indicator_Form(f)
if request.method == 'POST' and create_indicator_form.validate():
indicator_id = get_next_index('indicator', 'indicator_id')
ticker = create_indicator_form.security.data
if create_indicator_form.mva_10.data is True:
mva_10_day = 'Y'
mva_25_day = 'N'
else:
mva_10_day = 'N'
mva_25_day = 'Y'
row = [indicator_id, ticker, mva_10_day, mva_25_day]
add_data('indicator', row)
# adding relation
criteria_row = [session['strategy'][0], indicator_id]
add_data('criteria', criteria_row)
return redirect(url_for('home'))
create_indicator_form.strategies = session['strategy']
return render_template('create_indicator.html',
form=create_indicator_form)
When I try to run the flask app I'm thrown this error:
RuntimeError: working outside of request context
with a trace back to where I access the session object in the Create_Indicator_Form class.
I've realized since starting to try to fix this that it'd be more efficient to chose between the mva_10 and mva_25 with a select field but I would like to resolve this issue before refactoring.
Upvotes: 2
Views: 1993
Reputation: 55217
This is because the strategy = SelectField('strategy', session['strategy'])
line is executed when the file is loaded, as it is part of the Create_Indicator_Form
class definition.
At this time, you're indeed working outside of request context
Using a class factory will work here:
def CreateIndicatorForm():
class IndicatorForm(Form):
security = TextField('Ticker Name', [
validators.Required(),
validators.Length(min=1, max=6)])
mva_10 = BooleanField('10 day moving average')
mva_25 = BooleanField('25 day moving average')
strategy = SelectField('strategy', session['strategy'])
def validate_mva_10(form, field):
if form.mva_25.data is True and field.data is True:
raise ValidationError('You can only choose one reference')
if form.mva_25.data is False and field.data is False:
raise ValidationError('You must choose at least one reference')
return IndicatorForm
Be mindful that calling CreateIndicatorForm()
returns a Form class, so to instantiate an actual form, you need to use: CreateIndicatorForm()()
(i.e. "call" the class, like you would any other class to create a new instance).
When instantiating the form, you can (and should) pass arguments to the form constructor, such as the request data: CreateIndicatorForm()(request.form)
.
Also, making session['strategy']
an argument of the factory function would be better practice here - this would make the factory reusable outside of request context and would ensure you don't have to create a new form class for every single request.
Upvotes: 5