Create a Base Template for SuperDjango UI¶
Warning
As of this writing (release 4.1.0), SuperDjango UI is reasonably stable and the requirements for the base template are reasonably set. However, this does not mean further changes will not occur.
The Need for Base¶
The UI system expects a base.html
template. The base_template
variable is added to the context and defaults to
base.html
. Both superdjango.ui.interfaces.ModelUI
and superdjango.ui.interfaces.SiteUI
provide a base_template
attribute that may be used to override the setting.
Structure of the Theme¶
The theme/
directory contains the templates and files used to render the site, while the static/
directory
contains only static files that are site-wide or used to override the theme. This helps keep the theme more generic and
re-usable.
The suggested structure includes the following:
project_name
|-- source
| |-- static
| | |-- css
| | | `-- custom.css
| | |-- fonts
| | |-- images
| | `-- js
| | `-- custom.js
| |-- theme
| | |-- includes
| | | |-- breadcrumbs.html
| | | |-- footer.html
| | | |-- menu.html
| | | |-- messages.html
| | | |-- navbar.html
| | | `-- submenu.html
| | |-- static
| | | |-- css
| | | |-- fonts
| | | |-- images
| | | `-- js
| | |-- 403.html
| | |-- 404.html
| | |-- 500.html
| | |-- 503.html
| | |-- base.html
| | |-- sidebar_left.html
| | |-- sidebar_right.html
| | `-- three_columns.html
`--
Base Template HTML¶
The Start of the Base Template¶
The beginning of the template looks something like this.
{% load html_tags %}
{% load i18n %}
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{% block title %}{% endblock %} - {{ SITE_TITLE }}</title>
<link rel="shortcut icon" type="image/png" href="{% static "images/favicon.png" %}"/>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.13.0/css/all.css">
<link href="{% static "css/theme.css" %}" rel="stylesheet">
<link href="{% static "css/custom.css" %}" rel="stylesheet">
{# view css #}
{% for css in view_css %}
{{ css }}
{% endfor %}
{% block extra_css %}
{% endblock %}
{% block extra_head %}
{% endblock %}
</head>
<body class={% block body_class %}{% endblock %}">
Some things of note:
We load
html_tags
,i18n
, andstatic
template tags.FontAwesome is current the font used by the UI system. (Later releases may handle support of different icon libraries.)
The
theme.css
is loaded next, and then thecustom.css
to allow any overrides.view_css
is an iterable received from the view which allows the view to contribute CSS links or style blocks to the theme as needed.extra_css
allows templates to contribute CSS links or style blocks.extra_head
may be used by templates for any additional HTML to be included in the head tab.Finally, the
body_class
block is added to the opening body tag to allow body-wide styling as needed.
Pre-Content Body of Base Template¶
Next, we add the HTML for everything that appears before the principle content of the page. This may vary greatly depending upon the design you are adapting, but the important bit is the blocks to include.
<div class="container">
{% block navbar %}
{% include "includes/navbar.html %}
{% endblock %}
{% block messages %}
{% if messages %}
<div class="row" id="messages">
<div class="col">
{% for message in messages %}
{% html "alert" enable_close=True status=message.tags %}
{% endfor %}
</div>
</div>
{% endif %}
{% endblock %}
{% block breadcrumbs %}
{% if breadcrumbs %}
<div class="row" id="breadcrumbs">
<div class="col">
{% html "breadcrumbs" include_home=True home_url="/dashboard/" %}
</div>
</div>
{% endif %}
{% endblock %}
{% block heading %}
<div class="row" id="heading">
<div class="col-8">
{% block page_header %}{% endblock %}
</div>
<div class="col-4">
{% block call_to_action %}{% endblock %}
</div>
</div>
{% endblock %}
Some things of note:
Everything is wrapped in a block to allow overriding.
It’s good to supply element IDs to allow specific styling overrides if needed. It’s also nice when these IDs are the same as the blocks they wrap.
Each block is important to SuperDjango UI.
Defining the Base Layout¶
Next we come to the layout of the page.
{% block layout %}
{% block main %}
<div class="row">
<div class="col-12" id="content">
{% block content %}
{% endblock %}
</div>
</div>
<div class="row">
<div class="col-12" id="sidebar">
{% block sidebar %}
{% endblock %}
</div>
</div>
{% endblock %}
{% endblock %}
Some things of note:
Wrapping the main block in layout allows other templates to easily change the layout.
Closing Out The Base¶
The end of the base template adds a footer, closes the container, and includes JavaScript.
<div id="footer">
{% block footer %}
{% include "includes/footer.html" %}
{% endblock %}
</div>
</div>{# container close #}
{# core javascript and plugins #}
<script src="{% static "vendor/jquery/jquery.min.js" %}"></script>
<script src="{% static "vendor/bootstrap/js/bootstrap.bundle.min.js" %}"></script>
<script src="{% static "vendor/jquery-easing/jquery.easing.min.js" %}"></script>
{# globally enable bootstrap tooltips #}
<script>
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
</script>
{# https://docs.djangoproject.com/en/3.0/topics/i18n/translation/#module-django.views.i18n #}
<script type="text/javascript" src="{% url 'sd-javascript-catalog' %}"></script>
{# form #}
{% if form %}
{{ form.media }}
{% endif %}
{# view js #}
{% for js in view_js %}
{{ js }}
{% endfor %}
{# extra js #}
{% block extra_js %}
{% endblock %}
</body>
</html>
Some things of note:
Footer is an include which may include legal info, menus, etc.
Form styles and scripts are included after all other scripts, but before view JS.
view_js
is an iterable which allows views to contribute JavaScript to the rendered page.extra_js
allows templates to contribute JavaScript to the rendered page.
The Finished Base Template¶
The final template looks something like this:
{% load html_tags %}
{% load i18n %}
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{% block title %}{% endblock %} - {{ SITE_TITLE }}</title>
<link rel="shortcut icon" type="image/png" href="{% static "images/favicon.png" %}"/>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.13.0/css/all.css">
<link href="{% static "css/theme.css" %}" rel="stylesheet">
<link href="{% static "css/custom.css" %}" rel="stylesheet">
{# view css #}
{% for css in view_css %}
{{ css }}
{% endfor %}
{% block extra_css %}
{% endblock %}
{% block extra_head %}
{% endblock %}
</head>
<body class={% block body_class %}{% endblock %}">
<div class="container">
{% block navbar %}
{% include "includes/navbar.html %}
{% endblock %}
{% block messages %}
{% if messages %}
<div class="row" id="messages">
<div class="col">
{% for message in messages %}
{% html "alert" enable_close=True status=message.tags %}
{% endfor %}
</div>
</div>
{% endif %}
{% endblock %}
{% block breadcrumbs %}
{% if breadcrumbs %}
<div class="row" id="breadcrumbs">
<div class="col">
{% html "breadcrumbs" include_home=True home_url="/dashboard/" %}
</div>
</div>
{% endif %}
{% endblock %}
{% block heading %}
<div class="row" id="heading">
<div class="col-8">
{% block page_header %}{% endblock %}
</div>
<div class="col-4">
{% block call_to_action %}{% endblock %}
</div>
</div>
{% endblock %}
{% block layout %}
{% block main %}
<div class="row">
<div class="col-12" id="content">
{% block content %}
{% endblock %}
</div>
</div>
<div class="row">
<div class="col-12" id="sidebar">
{% block sidebar %}
{% endblock %}
</div>
</div>
{% endblock %}
{% endblock %}
<div id="footer">
{% block footer %}
{% include "includes/footer.html" %}
{% endblock %}
</div>
</div>{# container close #}
{# core javascript and plugins #}
<script src="{% static "vendor/jquery/jquery.min.js" %}"></script>
<script src="{% static "vendor/bootstrap/js/bootstrap.bundle.min.js" %}"></script>
<script src="{% static "vendor/jquery-easing/jquery.easing.min.js" %}"></script>
{# globally enable bootstrap tooltips #}
<script>
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
</script>
{# https://docs.djangoproject.com/en/3.0/topics/i18n/translation/#module-django.views.i18n #}
<script type="text/javascript" src="{% url 'sd-javascript-catalog' %}"></script>
{# form #}
{% if form %}
{{ form.media }}
{% endif %}
{# view js #}
{% for js in view_js %}
{{ js }}
{% endfor %}
{# extra js #}
{% block extra_js %}
{% endblock %}
</body>
</html>