.. index:: Templates ********* Templates ********* "Django’s template language is designed to strike a balance between power and ease. It’s designed to feel comfortable to those used to working with HTML. If you have any exposure to other text-based template languages, such as Smarty or Jinja2, you should feel right at home with Django’s templates." -- :djangodocs:`The Django template language | Django documentation ` To view the contents, which are generated by the views we just created, we now need to prepare the templates. The Django template system ========================== Django has it's own :djangodocs:`template system ` to create HTML which doesn't simply mix up Python code and HTML. This is done for a reason: The template system should be used to display the contents and not for programming logic. The Django template system provides various :djangodocs:`tags ` to perform simple operations. For example can the :djangodocs:`if tag ` be used to execute various tests or the :djangodocs:`for tag ` to iterate over a list. However the templates are not executed like regular Python code and the choice of functions is limited to the tags and filters provided by the Django template system. But it is possible to extend the template system with your :djangodocs:`own tags and filters `. Aside from that the Django template system has a powerful inheritance feature. With this feature it's possible to use a base template that contains all basic elements of the website and defines different blocks. Some or all of these blocks can be overwritten or extended by child templates which extend the base template. Those who are familiar with object orientated programming know this pattern. .. index:: HTML5 Boilerplate .. index:: Bootstrap 3 .. index:: jQuery .. _bootstrap-3: Create the base template ======================== At first create the base template with the help of the HTML5 Boilerplate. It comes together with `Bootstrap 3 `_, a popular HTML and CSS framework for developing responsive, mobile first websites and `jQuery `_, a fast, small, and feature-rich JavaScript library. Perform the following steps to download and copy the files: #. Click at the `Initializr Website `_ on "Bootstrap" #. In the section "H5BP Optional" check the "404 Page" option #. Finally click on the button "Download it!" #. Extract the ZIP archive #. Copy the file :file:`index.html` into the directory :file:`mysite/templates` and rename it to :file:`base.html` #. Copy the file :file:`404.html` into the same directory #. Copy the directories :file:`css`, :file:`img` and :file:`js` and the file :file:`apple-touch-icon.png` into the directory :file:`mysite/static` .. note:: To make the download of the HTML5 Boilerplate ZIP archive work your browser needs to accept the cookies set by the website. Now you need to adjust the base template :file:`base.html` so that Django is able to able to use the right path for the static files. Therefor you will use the :djangodocs:`static ` template tag from the staticfiles app. Template tags are written this way: ``{% tag %}``. Because the tag ``static`` is provided by an app it's not part of the default template tags and needs to be loaded first. This is done with the help of the :djangodocs:`load ` tag at the top of the template. Customize all highlighted parts in the head of :file:`base.html` as shown: .. literalinclude:: ../src/mysite/templates/base.orig.html :language: html+django :lines: 1-27 :emphasize-lines: 1, 13, 15, 22, 23, 25 :lineno-start: 1 Now follow the locations where the ``static`` tag needs to be placed at the end of the template :file:`base.html`: .. literalinclude:: ../src/mysite/templates/base.orig.html :language: html+django :lines: 87-107 :emphasize-lines: 5, 7, 9 :lineno-start: 87 Now replace the ``title`` HTML tag with the highlighted line: .. literalinclude:: ../src/mysite/templates/base.html :language: html+django :lines: 7-12 :emphasize-lines: 4 :lineno-start: 7 :dedent: 4 Here, the first (empty) block will be defined with the help of the :djangodocs:`block ` tag. Delete the ``
`` HTML tag overwritten with ```` including it's contents. Here can see the lines you have to delete: .. literalinclude:: ../src/mysite/templates/base.orig.html :language: html+django :lines: 56-63 :lineno-start: 56 :dedent: 4 Below you will see another ``
`` HTML tag follow by ````. Delete the HTML comment and the following HTML tag ``
`` including it's contents. Here can see the lines you have to delete: .. literalinclude:: ../src/mysite/templates/base.orig.html :language: html+django :lines: 66-83 :lineno-start: 66 :dedent: 6 Now add two additional blocks to the remaining ``
`` HTML tag; one for the headline and the other for the contents of the current page: .. literalinclude:: ../src/mysite/templates/base.html :language: html+django :lines: 50-63 :emphasize-lines: 2-7 :lineno-start: 50 :dedent: 4 That's it! The base template is done! Create the templates for the views ================================== Now the base template is finished. The next step is to create the missing templates for the views. First create the appropriate directory structure: :: $ mkdir -p marcador/templates/marcador This structure is necessary so that the template loader can load the templates. After that the app ``marcador`` has this structure: :: marcador |-- __init__.py |-- admin.py |-- migrations | |-- 0001_initial.py | `-- __init__.py |-- models.py |-- templates | `-- marcador |-- tests.py |-- urls.py `-- views.py .. note:: If the development server was running while creating the new directories you have to restart it. Otherwise the new directories wouldn't be recognized. Now create the templates inside the directory :file:`marcador/templates/marcador`. At first the template for the list view :file:`bookmark_list.html`: .. literalinclude:: ../src/mysite/marcador/templates/marcador/bookmark_list.html :language: html+django :linenos: This template extends the base template :file:`base.html` with the help of the :djangodocs:`extends ` tag. Therefor it's possible to extend the blocks defined inside the base template. Besides the already mentioned ``for`` tag is used to iterate over the list of bookmarks (``bookmarks``) and create a list entry for each. The template for the bookmark is included using the :djangodocs:`include ` tag. Now you create the template :file:`bookmark.html` which has been included in the previous template using the ``include`` tag: .. literalinclude:: ../src/mysite/marcador/templates/marcador/bookmark.html :language: html+django :lines: 1-17 :linenos: In this template a ``Bookmark`` object is available which is bound to the ``bookmark`` variable. In a template it's possible to access the attributes of an object, for example the title by using ``bookmark.title``. The attributes can be modified by filters, for example by using :djangodocs:`linebreaksbr ` which converts all ``
`` HTML tags to real line breaks. It is also possible to access related objects, for example the tags. Because ``bookmark.tags`` is a list of objects represented by a :ref:`manager object ` you can access the ``Tag`` objects only with the help of methods defined by the manager. ``bookmark.tags.count`` returns the number of tags. ``bookmark.tags.all`` creates an iterator which can be used in a loop. To call these methods in your Python code you have to put a pair of brackets at the end of the method (``bookmark.tags.count()``). If the methods are called in a template no brackets are allowed because you can't pass arguments to a method in a template. .. index:: url .. _url-template-tag: With the help of the :djangodocs:`url ` tag a link to the bookmark owners other bookmarks is created at the end of the template. Because the URL ``marcador_bookmark_user`` needs a user name we need to pass it as an argument to the template tag. That implies arguments can be passed to template tags. At last the template for the user's bookmarks must be created, :file:`bookmark_user.html`: .. literalinclude:: ../src/mysite/marcador/templates/marcador/bookmark_user.html :language: html+django :linenos: This template extends the template :file:`bookmark_list.html` because there are only very small differences between them. We need only to overwrite the blocks ``title`` and ``heading`` and can reuse the rest. Very convenient! Test the new templates ====================== After all templates have been created you can start the development server and have a look at the bookmarks, which you have created using the admin, at the front end under http://127.0.0.1:8000/. The list of bookmarks should look like this: .. image:: /images/marcador-latest-bookmarks.* :alt: Frontend Bookmark List View :align: center The login form at the top of the page does not work yet. But you will finish it right in the next chapter!