9. 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.”
Damit die Inhalte, die durch die eben erstellten Views erzeugt werden, auch sichtbar sind müssen nun noch die Templates angelegt werden.
9.1. Das Django Template System¶
Django hat ein eigenes Templates System zur Erzeugung von HTML, das nicht nur einfach Python Code mit HTML mischt. Das hat einen Grund: das Template System soll zur Darstellung der Inhalte genutzt werden, nicht zum Programmieren von Logik.
Das Django Template System stellt verschiedene Tags zur Verfügung, mit denen einfache Operationen durchgeführt werden können. Zum Beispiel können mit dem if Tag verschiedene Tests durchgeführt werden oder mit dem for Tag über eine Liste iteriert werden. Allerdings werden die Templates nicht wie normaler Python Code ausgeführt und die Auswahl von Funktionen ist auf die Tags und Filter beschränkt, die das Django Template System zur Verfügung stellt. Es ist aber auch möglich das Template System mit eigenen Tags und Filtern zu erweitern.
Außerdem besitzt das Django Template System eine mächtige Vererbungs-Funktion. Damit ist es möglich ein Basis-Template zu nutzen, dass alle wichtigen Elemente der Website enthält und verschiedene Blöcke definiert. Einige oder alle dieser Blöcke können dann von mehreren Kind-Templates, die vom Basis-Template erben, überschrieben oder erweitert werden. Wer mit Objektorientierter Programmierung vertraut ist wird dieses Modell kennen.
9.2. 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”
Im Abschnitt “H5BP Optional” wählst du “404 Page” aus
Zum Schluss klickst du auf den Button “Download it!”
Entpacke das ZIP Archiv
Kopiere die Datei
index.html
in das Verzeichnismysite/templates
und bennene sie inbase.html
umKopiere die Datei
404.html
in das gleiche Verzeichnis- Copy the directories
css
,img
andjs
and the fileapple-touch-icon.png
into the directorymysite/static
Bemerkung
Damit der Download des HTML5 Boilerplate ZIP Archivs funktioniert muss dein Browser die von der Website gesetzten Cookies akzeptieren.
Now you need to adjust the base template base.html
so that Django is
able to able to use the right path for the static files. Therefor you will use
the 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
load tag at the top of the
template. Customize all highlighted parts in the head of base.html
as
shown:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | {% load staticfiles %}
<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang=""> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang=""> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang=""> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang=""> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" href="{% static "apple-touch-icon.png" %}">
<link rel="stylesheet" href="{% static "css/bootstrap.min.css" %}">
<style>
body {
padding-top: 50px;
padding-bottom: 20px;
}
</style>
<link rel="stylesheet" href="{% static "css/bootstrap-theme.min.css" %}">
<link rel="stylesheet" href="{% static "css/main.css" %}">
<script src="{% static "js/vendor/modernizr-2.8.3-respond-1.4.2.min.js" %}"></script>
</head>
<body>
|
Hier folgen die Stellen, an denen das static
Tag am Ende des Templates base.html
einzusetzen ist:
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | <footer>
<p>© Company 2015</p>
</footer>
</div> <!-- /container --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="{% static "js/vendor/jquery-1.11.2.min.js" %}"><\/script>')</script>
<script src="{% static "js/vendor/bootstrap.min.js" %}"></script>
<script src="{% static "js/main.js" %}"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
e=o.createElement(i);r=o.getElementsByTagName(i)[0];
e.src='//www.google-analytics.com/analytics.js';
r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
ga('create','UA-XXXXX-X','auto');ga('send','pageview');
</script>
</body>
</html>
|
Nun ersetzt du das title
HTML Tag mit der markierten Zeile:
7 8 9 10 11 12 | <head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Marcador - {% block title %}{% endblock %}</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
|
Hier wird der erste (leere) Block mit Hilfe des block Tags definiert.
Delete the <div>
HTML tag overwritten with <!-- Main jumbotron for a
primary marketing message or call to action -->
including it’s contents. Here
can see the lines you have to delete:
56 57 58 59 60 61 62 63 | <!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<h1>Hello, world!</h1>
<p>This is a template for a simple marketing or informational website. It includes a large callout called a jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more »</a></p>
</div>
</div>
|
Below you will see another <div>
HTML tag follow by <!-- Example row of
columns -->
. Delete the HTML comment and the following HTML tag <div
class="row">
including it’s contents. Here can see the lines you have to
delete:
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | <!-- Example row of columns -->
<div class="row">
<div class="col-md-4">
<h2>Heading</h2>
<p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
<p><a class="btn btn-default" href="#" role="button">View details »</a></p>
</div>
<div class="col-md-4">
<h2>Heading</h2>
<p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
<p><a class="btn btn-default" href="#" role="button">View details »</a></p>
</div>
<div class="col-md-4">
<h2>Heading</h2>
<p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
<p><a class="btn btn-default" href="#" role="button">View details »</a></p>
</div>
</div>
|
Now add two additional blocks to the remaining <div>
HTML tag; one for the
headline and the other for the contents of the current page:
50 51 52 53 54 55 56 57 58 59 60 61 62 63 | <div class="container">
<div>
{% block heading %}{% endblock %}
</div>
<div>
{% block content %}{% endblock %}
</div>
<hr>
<footer>
<p>© Company 2015</p>
</footer>
</div> <!-- /container --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
|
That’s it! The base template is done!
9.3. 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
Bemerkung
Falls der Entwicklungsserver während des Anlegens der neuen Verzeichnisse lief, muss er neu gestartet werden, da die neuen Verzeichnisse sonst nicht bekannt sind.
Im Verzeichnis marcador/templates/marcador
legst du nun die Templates an.
Zuerst das Template für die Listenansicht bookmark_list.html
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | {% extends "base.html" %}
{% block title %}Latest bookmarks{% endblock %}
{% block heading %}
<h2>Latest bookmarks</h2>
{% endblock %}
{% block content %}
<ul class="list-unstyled">
{% for bookmark in bookmarks %}
<li class="well well-sm">{% include "marcador/bookmark.html" %}</li>
{% empty %}
<li>No bookmarks. :(</li>
{% endfor %}
</ul>
{% endblock %}
|
Dieses Template erbt mit Hilfe des Tags extends vom Basis-Template base.html
. Deshalb ist es möglich die im Basis-Template definierten Blöcke hier zu überschreiben. Außerdem wird das schon erwähnte Tag for
benutzt, um über die Liste der Lesezeichen (bookmarks
) zu iterieren und für jedes einen Listeneintrag zu erzeugen. Das Template für das Lesezeichen wird mit einem include Tag eingebunden.
Nun legst du das Template an, das im vorhergehenden mit Hilfe von include
eingebunden wurde, bookmark.html
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <a class="lead" href="{{ bookmark.url }}">{{ bookmark.title }}</a>
{% if bookmark.description %}
<br>{{ bookmark.description|linebreaksbr }}
{% endif %}
{% if not bookmark.is_public %}
<br><span class="label label-warning">private</span>
{% else %}
<br>
{% endif %}
{% if bookmark.tags.count %}
{% for tag in bookmark.tags.all %}
<span class="label label-primary">{{ tag|lower }}</span>
{% endfor %}
{% endif %}
<br>by <a href="{% url "marcador_bookmark_user" bookmark.owner.username %}">
{{ bookmark.owner.username }}</a>
{{ bookmark.date_created|timesince }} ago
|
In diesem Template steht ein Bookmark
-Objekt zur Verfügung, das an den Bezeichner bookmark
gebunden ist. Im Template ist es möglich auf die Attribute des Objekts zuzugreifen, zum Beispiel mit bookmark.title
auf den Titel. Die Attribute können durch Filter verändert werden, wie zum Beispiel durch linebreaksbr, dass alle Zeilenumbrüche zu <br />
HTML Tags umwandelt.
Es ist auch möglich auf die verbundenen Objekte zuzugreifen, wie zum Beispiel die Tags. Da bookmark.tags
aber eine Liste von Objekten ist, die durch ein Manager-Objekt repräsentiert wird, können wir nur mit Hilfe von Methoden auf die Tag
-Objekte zugreifen. bookmark.tags.count
liefert die Anzahl der Tags. bookmark.tags.all
erzeugt einen Iterator, der mit einem Loop benutzt werden kann. Würde man diese Methoden in Python aufrufen, muss ein Klammerpaar am Ende der Methode stehen (bookmark.tags.count()
). Werden die Methoden aber im Template aufgerufen, müssen die Klammern weggelassen werden, denn an Methoden kann man im Template keine Argumente übergeben.
Am Ende des Templates wird mit Hilfe des url Tags ein Link zur Liste der Lesezeichen des Benutzers erzeugt, dem dieses Lesezeichen gehört. Da der URL marcador_bookmark_user
einen Benutzernamen benötigt, müssen wir diesen als Argument an das Template Tag übergeben. An Template Tags können also Argumente übergeben werden.
Zuletzt muss dann das Template für die Lesezeichen eines Benutzers erstellt werden, bookmark_user.html
:
1 2 3 4 5 6 7 8 9 | {% extends "marcador/bookmark_list.html" %}
{% block title %}{{ owner.username }}'s bookmarks{% endblock %}
{% block heading %}
<h2>{{ owner.username }}'s bookmarks<br>
<small>{{ bookmarks.count }} bookmarks in total</small>
</h2>
{% endblock %}
|
Dieses Template erbt vom Template bookmark_list.html
, da es sich nur wenig von diesem unterscheidet. Wir brauchen lediglich die Blöcke title
und heading
überschreiben, alles andere können wir wieder benutzen. Praktisch!
9.4. Test the new templates¶
Nachdem alle Templates angelegt wurden startest du den Entwicklungsserver und kannst dir die Lesezeichen, die du im Admin angelegt hast, im Frontend unter http://127.0.0.1:8000/ ansehen.
The list of bookmarks should look like this:
The login form at the top of the page does not work yet. But you will finish it right in the next chapter!