Templating¶
This will cover various methods used in our jinja templates.
Base.html
¶
{% import ‘macros/nav_macros.html’ as nav %}
<!DOCTYPE html>
<html>
<head>
{% include 'partials/_head.html' %}
{# Any templates that extend this template can set custom_head_tags to add scripts to their page #}
{% block custom_head_tags %}{% endblock %}
</head>
<body>
{# Example dropdown menu setup. Uncomment lines to view
{% set dropdown =
[
('account stuff',
[
('account.login', 'login', 'sign in'),
('account.logout', 'logout', 'sign out'),
('2nd drop', [
('account.login', 'login 2', ''),
('3rd drop', [
('main.index', 'home 2', '')
])
])
]
),
('main.index', 'home 1', 'home')
]
%}
#}
{% block nav %}
{# add dropdown variable here to the render_nav method to render dropdowns #}
{{ nav.render_nav(current_user) }}
{% endblock %}
{% include 'partials/_flashes.html' %}
{# When extended, the content block contains all the html of the webpage #}
{% block content %}
{% endblock %}
{# Implement CSRF protection for site #}
{% if csrf_token() %}
<div style="visibility: hidden; display: none">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
</div>
{% endif %}
</body>
</html>
Macros: Password Strength (check_password.html
)¶
Refer to app/templates/macros/check_password.html
This uses the zcvbn password checker to check the entropy of the
password provided in the password field.
Given a specified field, the password checker will check the entropy
of the field and disable the submit
button until the give ‘level’ is surpassed
Macros: Form rendering (render_form
)¶
{% macro render_form(form, method='POST', extra_classes='', enctype=None) %}
{% set flashes = {
'error': get_flashed_messages(category_filter=['form-error']),
'warning': get_flashed_messages(category_filter=['form-check-email']),
'info': get_flashed_messages(category_filter=['form-info']),
'success': get_flashed_messages(category_filter=['form-success'])
} %}
{{ begin_form(form, flashes, method=method, extra_classes=extra_classes, enctype=enctype) }}
{% for field in form if not (is_hidden_field(field) or field.type == 'SubmitField') %}
{{ render_form_field(field) }}
{% endfor %}
{{ form_message(flashes['error'], header='Something went wrong.', class='error') }}
{{ form_message(flashes['warning'], header='Check your email.', class='warning') }}
{{ form_message(flashes['info'], header='Information', class='info') }}
{{ form_message(flashes['success'], header='Success!', class='success') }}
{% for field in form | selectattr('type', 'equalto', 'SubmitField') %}
{{ render_form_field(field) }}
{% endfor %}
{{ end_form(form) }}
{% endmacro %}
Render a flask.ext.wtforms.Form object.
Parameters:
form – The form to output.
method – <form> method attribute (default 'POST')
extra_classes – The classes to add to the <form>.
enctype – <form> enctype attribute. If None, will automatically be set to
multipart/form-data if a FileField is present in the form.
Render Form renders a form object. It calls the begin form macro.
Initially
a ‘flashes’ variable is set with ‘error’, ‘warning’, ‘info’, ‘success’
which
have values gathered from the get_flashed_messages method from
flask. Note
that all flashes are stored in SESSIOn with a category type. For most
of our
purposes, we only have form-error and form-success as our flash types
(the
second parameter in the flash function call seen in the views.
Then the begin_form macro is called and for each form field in the
provided
form render_form_field macro is called with the field.
All hidden fields (i.e. the CSRF field) and all submit fields is not
rendered
at this fime in render_form_field. In the render_form_field
method, render_form_input is called for each input in the form
field.
After that, the form_message macro is called with each of the flash types.
Lastly, the submit field is rendered. And the form is closed with the
end_form
macro
Macros: Start Form (begin_form
)¶
Set up the form, including hidden fields and error states.
begin_form is called from render_form. First a check is performed to
check
if there exists a field within the form with type equal to FileField.
This
check is performed via filter (“|”) in Jinja. This initial check
produces a
filtered object, the ‘list’ filter creates a iterable list which we
can then
check the length of with ‘length > 0’. So if this check passes, then
the enctype
must be set to multipart/form-data to accomodate a file upload.
Otherwise, there
is no enctype.
Then the form tag is created with a method default of POST, enctype
decided by the
check explained above. If there are errors (by field specific
validator errors or
if the flashes.error, flashes.warning, flashes.info, flashes.success
is not None,
then that class is added to the overall class of the form (along with
any specified
extra_classes, default = ‘’).
Lastly the hidden_tags are rendered. WTForms includes in this method
the rendering of
the hidden CSRF field. We don’t have to worry about that.
Example output:
<form action="" method="POST" enctype="multipart/form-data" class="ui form">
<div style="display:none;">
<input id="csrf_token" name="csrf_token" type="hidden" value="SOME_CSRF_TOKEN_HERE">
Macros: Flash message to Form (form_message
)¶
Render a message for the form. This is called from the render_form macro.
Recall the get_flashed_messages method. It will get the flash
message from
the SESSION object with a given cateogory_filter. Within the
render_form
macro, the flashes variable is set with attributes ‘errors’,
‘success’,
‘info’, and ‘warning’. The messages parameter for form_message
contains the
flash messages for the respective attribute specified in
flashes[‘some_attr’].
The form_message macro is called after all form fields have been
rendered,
except for the Submit field. A div is created with class= ‘ui CLASS
message’
class being either error, success, info, or warning. This div is only
created
if there are messages for a given flashes type! For each of the
messages in
the flashes type, the message is filtered to only contain escaped HTML
chars
and appended within the div ul as a list element.
Example Output:
<div class="ui error message">
<div class="header">Something went wrong.</div>
<ul class="list">
<li>Invalid email or password.</li>
</ul>
</div>
Macros: Render a form field (render_form_field
)¶
Render a field for the form. This is rather self explanatory.
If the field is
a radio field (RadioField WTForms object) extra_classes has an added
class of
‘grouped fields’ since all the options of a Radio Field must be styled
in this
way to display together.
If there is a validation error on the form field, a error class is
added to the
field div (to make the field colored red). Then the
render_form_input macro is
called with field object itself as a parameter. Any validation errors
are then
added with a sub-dev with content field.errors (we only show the first
validation
error for the given error for simplicity) and filter for HTML safe
chars.
Partials: _flashes
¶
See the macros/form_macros for extended explanation of the
get_flashed_messages(category_filter) method. This macro renders
general flash methods that appear at the top of the page. We render
by flash type and create a separate ‘ui {{ class }} message’ div
for each message within a specific flash type. Error = red,
warning = yellow, info = blue, success = green.
Partials: _head
¶
This method contains all the assett imports (i.e. imports for scripts
and styles for the app)
Note that the asssets will be contained in the
static/webassets-external folder when the app
is in debug mode.