I am building a small app using a forex converter api, it’s function is to take one currency, and convert a value into the new currency. I seem to be getting caught when accessing my class “Survey” everything I try to get data from my html form. My program is getting caught on self.convertFrom=request.form[‘convertFrom’] and the python debugger is giving me “RuntimeError: Working outside of request context.” I would greatly appreciate if someone can show/explain to me what it is im doing wrong here.
app.py
from flask_debugtoolbar import DebugToolbar from forex_python.converter import CurrencyRates from handleForm import Survey app = Flask(__name__) survey = Survey() result=["Give me something to convert!"] @app.route("/") def home_page(): """Loads home page where user can enter their first conversion""" return render_template('index.html') @app.route("/conversion") def show_conversion(): """shows the users conversion""" return render_template('convSubmit.html', result=result) @app.route("/conversion/new", methods=["POST"]) def add_conversion(): """clear old conversion from list and add new""" result=[] result.append(survey.convertCurrency()) return redirect("/conversion")
handleForm.py
from flask import Flask, render_template, request from forex_python.converter import CurrencyRates c = CurrencyRates() class Survey(): def __init__(self): self.convertFrom=request.form['convertFrom'] <---gets caught here self.convertTo=request.form['convertTo'] self.value=request.form['value'] def convertCurrency(self): currencyFrom = self.convertFrom currencyTo = self.convertTo getValue = int(self.value) result = c.convert(currencyFrom, currencyTo, getValue) return result
Advertisement
Answer
The request variable will be available only when a request is active. In simple terms it will be available only when it is invoked by a view function handling a route.
In your case, you are trying to initialise the survey object outside any root function. That line will be invoked when the app server is started, before any request has been reserved, and hence flask is throwing an error saying that you are invoking it outside of request context.
To fix it, you should move the survey = Survey()
inside a view function
@app.route("/conversion/new", methods=["POST"]) def add_conversion(): """clear old conversion from list and add new""" result=[] survey = Survey() result.append(survey.convertCurrency()) return redirect("/conversion")
While this would fix the problem, it is still not a good pattern to make that class constructor to directly access the request global.
If you need the constructor itself to initialize these params, you can pass these as arguments to the constructor and then pass them when initializing
from flask import Flask, render_template, request from forex_python.converter import CurrencyRates c = CurrencyRates() class Survey(): def __init__(self, convertFrom, convertTo, value): self.convertFrom=convertFrom <---gets caught here self.convertTo=convertTo self.value=value def convertCurrency(self): currencyFrom = self.convertFrom currencyTo = self.convertTo getValue = int(self.value) result = c.convert(currencyFrom, currencyTo, getValue) return result
And then change the view function to pass the values to the constructor
@app.route("/conversion/new", methods=["POST"]) def add_conversion(): """clear old conversion from list and add new""" result=[] survey = Survey(request.form["convertFrom"], request.form["convertTo"], request.form["value"]) result.append(survey.convertCurrency()) return redirect("/conversion")