Templates

At this point our application contains all of our essential functionality. However, it doesn’t exactly look like a blog. While the scaffolding templates are perfectly acceptable in some situations, there are many situations where you’d like to create your own.

Layouts

Most templates will use a layout. Layouts provide the HTML skeleton for templates. You can think of them as a wrapper of sorts.

Layouts are stored in app/templates/layouts. Ferris provides two layouts for you: A simple Twitter Bootstrap layour named default.html and one layout that’s used for the admin scaffolding named admin.html.

Note

If you’re using the scaffold templates, Ferris will choose which layout to use based on the prefix. Ferris uses admin.html for the admin prefix, and default.html for everything else.

You can override Ferris’ default.html by creating your own. We’re going to add some navigation at the top of our application.

Create app/templates/layouts/default.html:

<!doctype html>
<html>
<head>
    <title>{{scaffolding.title}}</title>

    <link rel="stylesheet" type="text/css" href="/ferris/css/bootstrap.min.css">
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script type="text/javascript" src="/ferris/js/bootstrap.js"></script>

</head>
<body>
    <div class="container">
        {% block layout_content %}
        {% endblock %}
    </div>
</body>
</html>

This is a very simple layout that more or less mimics what Ferris’ default.html provides. The important piece to note is the layout_content block. This creates a spot where child templates can insert content.

Listing

Presenting blog posts in a table isn’t exactly the best way to it. We’d like to show the content of the post and present everything in a way that’s slightly easier on the eyes. At the moment we’re using the scaffold’s template for list, but we can easily use our own by creating app/templates/posts/list.html:

{% extends "layouts/default.html" %}
{% import "scaffolding/macros.html" as scaffold with context %}

{% block layout_content %}
    {% for post in posts %}
    <div class="media">
        <div class="media-body">
            <h4 class="media-heading">{{post.title}}</h4>
            <h6 class="media-heading">By {{post.created_by}} on {{scaffold.print(post.created)}}</h6>
            <p>{{post.content}}</p>
        </div>
    </div>
    {% endfor %}
{% endblock %}

Let’s walk through this one:

  • First, we inherit from the default layout we created earlier.
  • We also import the scaffold’s macros. This provides us with a couple of useful helpers.
  • We specify the content to put in the layouts layout_content block.
  • We iterate over each post in the posts variable and create a media div for it.
  • We use the scaffold.print method to output a nicely formatted and localized date.

Opening up http://localhost:8080/posts shows our much nicer list of posts.

It would be nice to have an edit link as well. Add this before the closing tag of <div class="media">:

{% if this.user == post.created_by %}
    <a href="{{uri('posts:edit', key=post.key.urlsafe())}}">Edit</a>
{% endif %}

Now http://localhost:8080/posts shows an edit link for posts that the currently logged in user has created.