.. _flask-templates: HTML Templates ============== In our first Flask app, we simply returned a string to display on a webpage. By including HTML tags, we provided some structure for the content. However, this is inefficient. Even for simple webpages, properly formatting the strings becomes tedious, and avoiding errors is difficult. Since every page needs its own string, adding these to our Python functions clutters up our code and makes our program harder to debug. A better approach is to put all of the HTML in a separate file. This idea lets us separate the *logic* of our application (the Python code) from the *view* (what the user sees in their browser). Why reinvent the wheel? We already learned how to create nice webpages using HTML and CSS, so we can build those files and include them in our project. Instead of returning a string, we have each Python function point to a specific ``.html`` file. Flask sends that file to the browser, which *renders* the webpage we want. What are Templates? ------------------- .. index:: ! template single: Flask; template A **template** is an outline that can be used multiple times to produce similar results. For example, think of a simple thank-you note: .. figure:: figures/form-letter.png :alt: A thank-you note with blanks for filling in names, etc. :width: 70% Warning: Form letters don't work so well with close relatives. With this *template*, we can send out dozens of messages very quickly. Most of the text stays the same. We just need to fill in the blanks (or write some code to do it for us). The template itself stays the same, but each message looks slightly different. For our web applications, we can use a ``.html`` template to fill in most of the content for a page. Then we call a Python function to fill in the blanks. Templates with Flask -------------------- To use a template in Flask, we need to organize our project files in a very specific way. We'll start by creating a ``templates`` directory. #. Save and commit your work, then checkout a new branch called ``template-practice``. #. In the File Explorer, use the buttons to create a new directory called ``templates``. .. figure:: figures/templates-in-filetree.png :alt: File tree showing the 'templates' directory inside 'hello_flask'. #. Any file we want to use as a template MUST go inside this directory. If we don't put it there, then Flask won't be able to find the file when we need it. Add a Template ^^^^^^^^^^^^^^ Inside the ``templates`` folder, create a new file called ``favorite_form.html``. Paste in this HTML code: .. sourcecode:: html :linenos: Flask Template

A Few Of My Favorite Things





In the :ref:`Local HTML/CSS section ` we learned how to open HTML files in the browser. Now, however, we are going to have Flask do that job for us. The ``render_template`` Function ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. index:: single: Flask; render_template #. Return to the ``hello.py`` program. In order to use the template we just created, we need to update the first ``import`` statement: .. sourcecode:: Python :linenos: from flask import Flask, render_template #. The ``render_template`` function contains the code we need to find a file and send it to the browser. We do NOT need to know how the function actually works. All we need to remember is the syntax for calling it: .. sourcecode:: Python render_template("name_of_template") ``name_of_template`` MUST include the extension for the file, like ``.html``. #. Next, add this new function to ``hello.py``: .. sourcecode:: Python @app.route('/form') def form(): return render_template("favorite_form.html") #. Save the code, then run the program. Open a browser and navigate to ``http://127.0.0.1:5000/form``. Ta da! There's our form. .. figure:: figures/favorite-form.png :alt: An HTML form with four input fields plus a Submit button. Flask sent the ``favorite_form.html`` file to the browser. ``render_template("favorite_form.html")`` locates the HTML file in our project. ``return`` sends this information to Flask, which passes the file to the browser. Note that the URL in the address bar is NOT the location of the file on our computer. The template is *on the server*, so its web address reflects this. Our form doesn't actually do anything yet, but we'll deal with that on the next page. .. _template-placeholders: Sending Data to a Template -------------------------- One of the benefits of using a template is that we can pass data to the file and change its appearance in the browser. To practice this, let's add another HTML file to the ``templates`` directory. It will be a copy of the thank you note shown at the top of this page. #. Create a new file called ``tynote.html`` in the ``templates`` folder. #. Paste in this code: .. sourcecode:: html :linenos: Thank You Note

Dear {{name}},

Thank you so much for the {{gift}}. I'm having lots of fun {{verb}} with it. It's already made me a better {{noun}}!

{{closing_word}},

{{author}}

#. Note that instead of blanks, the text includes *placeholders* where we want to insert data. Each placeholder contains a variable inside a set of double curly braces ``{{}}``. #. Now add this function to ``hello.py``: .. sourcecode:: Python @app.route('/thanks') def thanks(): return render_template("tynote.html") #. Save the code, then run the program. Open a browser and navigate to ``http://127.0.0.1:5000/thanks``. .. figure:: figures/thank-you-blanks.png :alt: Thank-you text with blank spaces. :width: 80% Notice that the text appears on the screen, but NOT any of the placeholders like ``{{name}}``. To fill in the blank spaces, we need to send some data to the template. Arguments with ``render_template`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Let's start by filling in the ``{{name}}`` placeholder. We do this by adding another argument to ``render_template`` function call. The general syntax is: .. sourcecode:: Python render_template("name_of_template", placeholder_name = value) ``placeholder_name`` is the variable used in the template. ``value`` is what we want to display on the page. For our thank-you message, this looks something like: .. sourcecode:: Python render_template("tynote.html", name = "Bob") Updating the Python code and refreshing the page gives us: .. figure:: figures/ty-note-name.png :alt: Template text with the name space filled in with 'Bob'. :width: 80% .. admonition:: Tip Instead of hard-coding values inside ``render_template``, we can use variables instead. .. sourcecode:: Python @app.route('/thanks') def thanks(): person = "Bob" action = "dancing" return render_template("tynote.html", name = person, verb = action) .. admonition:: Try It! #. Add arguments to ``render_template()`` to complete the thank you note. .. figure:: figures/ty-note-done.png :alt: Template text with all placeholders filled. The ``tynote.html`` template will all placeholders filled. #. Move the ``name = person`` argument to the end of the list in ``render_template()``. Does this change where the ``name`` value appears on the webpage? Expressions in Placeholders --------------------------- ``render_template`` sends data to a selected file. When Flask sees a placeholder like ``{{name}}`` in that template, it replaces it with the matching value from the data. Besides variables, Flask can also evaluate simple expressions. .. admonition:: Try It! #. In ``tynote.html``, replace the ``{{name}}`` placeholder with ``{{name*3}}``. What happens? #. Replace ``{{verb}}`` with ``{{verb.capitalize()}}``. What happens? #. Replace ``{{gift}}`` with ``{{gift=='wand'}}``. What happens? Video Summaries --------------- Here is a walkthrough for creating an HTML template, then rendering it from a Flask application. .. raw:: html
The next clip shows how to send data to a webpage from a Python program. .. raw:: html
Check Your Understanding ------------------------ .. admonition:: Question In ``render_template()``, the name of the template must come first in the list of arguments. But what about the other entries? Does changing the order of the arguments change where their values appear on the webpage? .. raw:: html
  1. Yes
  2. No

.. Answer = b