[Tourist Attractions] Build Python Web Apps with Flask: Form Submitting

I’m currently working on the project from the Jinja2 Templates and Forms section of this course (https://www.codecademy.com/learn/paths/build-python-web-apps-flask).

I’ve followed the instructions to the letter, and everything worked well until the last two steps involving collecting the form data and redirecting the application flow.

28 @app.route("/add_location", methods=["POST"])
29 def add_location():
30  ## Validate and collect the form data
31  add_form = AddLocationForm()
32
33 if add_form.validate_on_submit():
34      name=add_form.name.data
35      description=add_form.description.data
36      category=add_form.category.data
37      visit.add(name, description, category)
38
39  ## Redirect to locations route function
40  return redirect(url_for("locations", category=category))
41
42 @app.route("/")
43 def index():
44
45    ## Redirect to locations route function
46    return redirect(url_for("locations", category="recommended"))

When I try to submit a new location in the browser, I get an “UnboundLocalError: local variable ‘category’ referenced before assignment” which points to File “/home/ccuser/workspace/tourist-attractions-app-project/app.py”, line 40, in add_location.

It seems to me that once I fill out the form and click submit, add_form.validate_on_submit() should evaluate to True, which would create the variable category and cause it to be assigned the value that exists in the category field of the add_form object. If this were the case though, wouldn’t category be assigned before I reference it in line 40?

Thanks in advance for any feedback.

2 Likes

I think you need to have it declared in a way all conditionals meet it…

If you set it to some default value like category = "" or some filter before the if-statement you should be fine? But that wouldn’t get the effect you want.

So maybe you can do a return where category is set and the return is nested inside the if-statement, and a return for when it’s not set and you don’t pass category into the url_for

def add_location():
30 ## Validate and collect the form data
31 add_form = AddLocationForm()
32
33 if add_form.validate_on_submit():
34      name=add_form.name.data
35      description=add_form.description.data
36      category=add_form.category.data
37      visit.add(name, description, category)
38      return redirect(url_for("locations", category=category))
39  
40 return redirect(url_for("locations"))

Thanks for the suggestions!

I tried your second suggestion with a slight tweak:

28 @app.route("/add_location", methods=["POST"])
29 def add_location():
30  ## Validate and collect the form data
31  add_form = AddLocationForm()
32
33 if add_form.validate_on_submit():
34      name=add_form.name.data
35      description=add_form.description.data
36      category=add_form.category.data
37      visit.add(name, description, category)
38      ## Redirect to locations route function
39      return redirect(url_for("locations", category=category))
40  
41 return redirect(url_for("index"))
42
43 @app.route("/")
44 def index():
45
46    ## Redirect to locations route function
47    return redirect(url_for("locations", category="recommended"))

but now clicking the submit button doesn’t seem to do anything – the page doesn’t change and the form stays filled out.

1 Like

Hm, couple of things you can check in the terminal:

Is add_form.validate_on_submit() evaluating as True?
If you print name, description, etc, does that show up in the terminal when you click?
Do you need name and description to go through as well after the request?

Can you describe what you want to do with the info once you get them from the form?

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.