[Tourist Attractions] Build Python Web Apps with Flask

Jinja2 Templates and Forms

Hello
I’m working on “Tourist Attractions” project in “Build Python Web Apps with Flask” and I got stuck at some instructions because I can’t find the code mentioned in the instruction. Can someone help me where can I find them?

###Can’t find tags mentioned in instructions in location.html
Step 5

  1. Inside the <tbody class="loctable"> tags create a for loop that surrounds the <tr> tags
  2. Inside the <td class="loc"> tags insert the name attribute of the location object
  3. Inside the <td class="desc"> tags insert the description attribute of the location object

Step 7

  1. Inside the <td class="btns"> tags create an if statement that surrounds the <form> tags

Step 14

  1. Inside the <form class="addform" tag set the action attribute to url_for() that takes the add_location route function as an argument

###Can’t find the statement mentioned in instructions in app.py
Step 10

  1. Replace the [(None, None)] statement with the output of the items() method of the request objects form attribute
3 Likes

Hello @core9221442141, and welcome to the Codecademy Forums!

It appears that the developers of this course omitted some details from the code that they gave us. For example, they did not get around to assigning classes to some tags, and they left out numbers within comments such as these:

            <!-- STEP -->

As a result, this Tourist Attractions project may take the form of a backcountry expedition requiring some “roughing it”.

Judging from the information that they did provide us, it seems that after we have completed the fifth step, a portion of the locations.html file should appear something like the following:

    <tbody class="loctable">
        <!-- Start of STEP 5 -->
        {% for location in locations %}
        <tr>
          
          <td class="loc">{{location.name}}</td> <!-- STEP -->
          <td class="desc">{{location.description}}</td> <!-- STEP placeholder text?-->
          
          <td>
            <!-- STEP -->
            <form method="POST">
              <input type="submit" class="up" name="" value=&#8599;> <!-- STEP -->
              <input type="submit" class="del" name="" value="X"> <!-- STEP -->
            </form>
            <!-- STEP -->
          </td>
        </tr>
        {% endfor %}
        <!-- End of STEP 5 -->
    </tbody>

We should consider reporting the omissions of portions of the provided code as a bug.

3 Likes

For step 7, we will also need to provide a class that is missing from the code.

Look for the first <form method="POST"> tag in the locations.html file. Provide the missing class for the <td> tag that encloses that form. When we are done making corrections and following the instructions, it appears that we should have this:

          <td class="btns">
            <!-- STEP 6, 7 -->
            {% if location.category in ["recommended", "tovisit"] %}
            <form method="POST">
              <input type="submit" class="up" name="{{ location.name }}" value=&#8599;> <!-- STEP -->
              <input type="submit" class="del" name="{{ location.name }}" value="X"> <!-- STEP -->
            </form>
            {% endif %}
            <!-- End STEP 7 -->
          </td>

Instruction 9, includes this:

Inside the locations() route function replace the False condition of the if statement with a check that the request object’s method attribute equals POST

However, the locations() function is given as follows:

@app.route("/<category>", methods=["GET", "POST"])
def locations(category):
  locations = visit.get_list_by_category(category)
  ## Check the request for form data and process

  ## 1) Return the main template with variables
  return render_template("locations.html", category=category, categories=categories, locations=locations)

There is no if statement there. Are we looking in the wrong place for it?

3 Likes

Hi there! This project was a little rough for the above reasons, but I finished (though it took two days). When I run the app now, I get a RunTimeError: Working outside of request context.
Traceback (most recent call last):

  • File “C:/…/app.py”, line 14, in *
  • add_form=AddLocationForm()*
    I’ve tried adding in “with app.app_context():” but still nothing.
    I can get the app to run if I omit the () so that it is: “add_form=AddLocationForm”, but none of the buttons or forms work.
    Any thoughts?
1 Like

Thank you for your swift responses and lots of work!!

I just reported this as a bug. Hope Codecademy will take action soon…
[Tourist Attractions] Build Python Web Apps with Flask - Unable to complete due to lack of instructions

1 Like

Thanks for the bug report, @core9221442141 . I also submitted one, and the Codecademy team that created the course has been alerted to our reports as well as to this thread. @offsetkeyz, the team will also learn about the problem you encountered when they see your post.

Within this discussion, we can continue to discuss any problems we have with the project, and can look forward to seeing them addressed.

Without the parentheses, you are not instantiating any AddLocationForm. You are only assigning a reference to that class to add_form.

We would need to see your code in order to figure out what happens when you do include the parentheses.

Thank you so much for the feedback and report! Learners like y’all help us make our content as best as it can be. We are working on making changes to the project right now that address these issues. I will follow up here when the changes have been finalized.

2 Likes

All changes have been made to the project per the feedback above. Thank you all again for your help! Definitely let us know if you catch anything else :slight_smile:

1 Like

Hi, @javaninja55993,

Thanks for the changes. The instructions are much easier to follow.

There are some inconsistencies in step 21.

Included there are:

  1. In the add_location() route function replace the empty string in the return statement with redirect()
  2. As the argument for redirect use url_for() and pass the locations route function and set the category keyword argument to the local variable category
  3. In the index() route function replace the empty string in the return statement with redirect()
  4. As the argument for redirect use url_for() and pass the locations route function and set the category keyword argument to "recommended"

However, the hint contradicts this with:

In the add_location route function return statement call redirect() with url_for() as an argument. The arguments of url_for() are "location" and category=category .

In the index route function return statement call redirect() with url_for() as an argument. The arguments of url_for() are "location" and category="recommended" .

Note the switch from "locations" to "location".

Either way, adding a location brings up a traceback, upon pressing the button. The traceback includes this line, within the add_location function, as part of the issue:

return redirect(url_for("locations"), category=category)

Here is that function, as I have it:

@app.route("/add_location", methods=["POST"])
def add_location():
  ## Validate and collect the form data
  add_form = AddLocationForm()
  if add_form.validate_on_submit():
      name=add_form.name.data
      description=add_form.description.data
      category=add_form.category.data
      visit.add(name, description, category)

  ## Redirect to locations route function
  return redirect(url_for("locations"), category=category)

… and here is the locations function:

@app.route("/<category>", methods=["GET", "POST"])
def locations(category):
  locations = visit.get_list_by_category(category)
  ## Check the request for form data and process
  if request.method == "POST":
    [(name, action)] = request.form.items()
    if action == UP_ACTION:
      visit.moveup(name)
    elif action == DEL_ACTION:
      visit.delete(name)
  ## Return the main template with variables
  return render_template("locations.html", category=category, categories=categories, locations=locations, add_location=AddLocationForm())

EDIT (July 23, 2020):

As a workaround, I changed the final line in the add_location() function to:

  return redirect("/recommended")

It’s not ideal, but it avoids the error.

1 Like

Thanks for the report! I’ll revisit step 21 today and follow up.

Thank you so much for your quick response!! I completed this content!!

Can you share the details of traceback? I think I did the same and worked without any troubles.

I have restored my code back to the state that I thought had produced the traceback, but now am unable to reproduce the problem.

¯\_(ツ)_/¯

As per the above, perhaps we could leave things as they are for now, unless someone else demonstrates that they have followed the instructions and then received a traceback upon submitting a new location.

Thanks for the great work. :smile:

2 Likes

Hi. I believe I have received this traceback error on step 21 when submitting a new location as explained above. The error is

UnboundLocalError

UnboundLocalError: local variable 'category' referenced before assignment

I have completed the project twice in case I missed something but I ended with the same result. I also notice that the redirect function does nothing when going to the index ("/") route.

def index():

  ## Redirect to locations route function
  return redirect(url_for("locations", category="recommended"))

When going this route nothing appears on screen and the status wheel just keeps spinning.

Hello @mackz88, and welcome to the Codecademy Forums.

Please post a copy of your code and the entire traceback, so that someone can diagnose the problem.

@javaninja55993, are you still involved with refining the content of this project? If so, please let us know whether we can identify the nature of the problem, after the most recent poster has posted relevant code along with a copy of the reported traceback. If responsibility for the content of this project has been transferred to someone else, please let us know how we can direct that person’s attention to the reported problem. Thanks for the good work that you have devoted to this project.

I have tried running the code using a different browser (chrome) and no longer am receiving the traceback error. I believe it had something to do with my ad-blocking extensions as turning them off also remedied the issues.

I am however still having issues with the page redirecting after the form entry and when visiting the “/” route.

Here is the traceback if still relevent - https://i.imgur.com/ueUoON9.png

Here is my code for this project - https://gist.github.com/Mmackz/2485cd3913e6550b259fd1b424de3f0d

Yeah, I redid the entire project, checking and rechecking the instructions carefully, and entered a new location:

The result was a traceback:

* #### File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line  *2463* , in  `__call__`

return self.wsgi_app(environ, start_response)

* #### File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line  *2449* , in  `wsgi_app`

response = self.handle_exception(e)

* #### File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line  *1866* , in  `handle_exception`

reraise(exc_type, exc_value, tb)

* #### File "/usr/local/lib/python3.6/dist-packages/flask/_compat.py", line  *39* , in  `reraise`

raise value

* #### File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line  *2446* , in  `wsgi_app`

response = self.full_dispatch_request()

* #### File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line  *1951* , in  `full_dispatch_request`

rv = self.handle_user_exception(e)

* #### File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line  *1820* , in  `handle_user_exception`

reraise(exc_type, exc_value, tb)

* #### File "/usr/local/lib/python3.6/dist-packages/flask/_compat.py", line  *39* , in  `reraise`

raise value

* #### File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line  *1949* , in  `full_dispatch_request`

rv = self.dispatch_request()

* #### File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line  *1935* , in  `dispatch_request`

return self.view_functions[rule.endpoint](**req.view_args)

* #### File "/home/ccuser/workspace/tourist-attractions-app-project/app.py", line  *45* , in  `add_location`

return redirect(url_for("locations", category=category))

> UnboundLocalError: local variable 'category' referenced before assignment

It appears that this block in the add_location function did not execute:

  if add_form.validate_on_submit():
      # 20)
      name = add_form.name.data
      description = add_form.description.data
      category = add_form.category.data
      visit.add(name, description, category)

I suspect we need a fix from the Codecademy staff.

1 Like