SnarkShark SnarkShark - 3 months ago 18
Python Question

Can I use one WTForm for multiple @app.route's?

I need to access information from my WTForm in multiple @app.route's in my

app.py
, so that I can post data visualization for my app. Currently, I have a
@app.route(/home/)
page and user-entered text on this page is processed by a WTForm, and then passed to
@app.route(/results/
) where my code does some data analysis and then 1) displays some results and 2) saves some other information to JSON, which is to be used for D3 in its own
@app.route(/visualization/)
. Because of complications with Javascript, I want to display my D3 visualization in an
iframe
of its own. Right now I can load the
/home/
page, type in text and hit "Submit", which then redirects me to
/results/
, and prints everything correctly except the
iframe
. The problem is: I'm unable to get
@app.route(/visualization/)
to take information from my WTForm (in the same way that
results
is able to), so that the image can load the proper JSON file.

Here's some of my code to better illustrate the problem.

app.py
:

# Home
@app.route("/home/", methods=["GET", "POST"])
def gohome():
error = None
with open('somedata.pickle', 'rb')as f:
some_content = pickle.load(f)
try:
if request.method == "POST":
attempted_pmid = request.form['pmid']
except Exception as e:
#flash(e)
return render_template("dashboard.html", error=error)
return render_template("dashboard.html", some_content=some_content)


# My WTForm for handling user-entered pmids
class pmidForm(Form):
pmid = TextField('PubmedID')

# Results
@app.route("/results/", methods=["GET", "POST"])
def trying():
form = pmidForm(secret_key='potato')
try:
if request.method == 'POST':
entry = form.pmid.data #THIS IS THE USER INPUT FROM THE FORM #referencing 'class pmidForm'
pmid_list = multiple_pmid_input(entry) #list for handling multiple pmids
print(pmid_list)


for user_input in pmid_list:
print(str(user_input))
user_input = str(user_input)
# DO STUFF HERE #
# SAVE A JSON FILE TO A FOLDER #

return render_template('results.html')
except Exception as e:
return(str(e))


# Visualization
@app.route('/visualization/', methods=["GET", "POST"]) #for iframe
def visualization():
#need to get last user_input
form = pmidForm(secret_key='potato')
try:
if request.method == 'POST':
entry = form.pmid.data
pmid_list = multiple_pmid_input(entry)

for user_input in pmid_list:
print("This is the user input on /visualization/")
print(str(user_input))
user_input = str(user_input)

#Load
if user_input == pmid_list[-1]:
load_path = '/the/path/'+str(user_input)+'/'
completeName = os.path.join(load_path, ((str(user_input))+'.json'))
print(completeName)

with open(completeName, 'w') as load_data:
jsonDict = json.load(load_data)
print(jsonDict)
return render_template('visualization.html', jsonDict=jsonDict)
except Exception as e:
return(str(e))


So as I have it now,
home
and
results
work fine together with the existing WTForm I have. I will do everything properly. But in
results.html
I need to load
visualization.html
in an
iframe
like so:

Line in
results.html
:

<iframe id="vis1" src="https://www.website.com/visualization/" width="1000" height="1000"></iframe>


With this configuration if I run my
app.py
, everything displays like normal except the
iframe
which displays:


local variable 'jsonDict' referenced before assignment


Here, I assume that's in reference to my
visualization.html
which has the Jinja code:

var myjson = {{ jsonDict|tojson }};


So obviously the
@app.route(/visualization/)
isn't getting the information from the WTForm as it should. How can I get this second
@app.route
to recognize the content in the WTForm like how it works with
results
?

Also, this may seem hacky, but I have very good reasons for putting my D3 in an
iframe
. It's because I need to be able to toggle through multiple html's like
/visualization
/ that each have complicated Javascript that conflict with each other. The best thing I can do is isolate them all in
iframe
's.

Answer

The answer is no, you can't submit one form to multiple routes or share data between multiple routes. My sollution to the problem of needing to share data between multiple routes was to create dynamic URLs. So instead of always going to a results page, it would go to results/1234 and this way I was able to access the "1234" and use it in that html.

Comments