Welcome to django-uswds-forms’s documentation!¶
Welcome to the django-uswds-forms documentation!
This package provides Django Forms integration with the U.S. Web Design Standards.
Introduction¶
Motivation¶
The U.S. Web Design Standards are awesome, but there’s a
few barriers that make it difficult to use with
django.forms.Form
. For example:
- The CSS classes used by Django’s default renderer for things like errors and help text are not the same as those used by USWDS.
- Individual checkboxes and radio buttons have different HTML markup than that rendered by Django forms.
- Dates are split up into three separate month/day/year fields.
- Dates and sets of checkboxes and radios need to use either
<legend>
or ARIA group roles to be accessible.
We implemented solutions for the above issues in CALC but wanted to factor them out for reuse by other Django projects, so we created this package.
Philosophy¶
This package has the following core values:
- Low cognitive overhead. Where possible, this package aims to
build upon the shoulders of the
django.forms.renderers
API introduced in Django 1.11. This means that, aside from understanding that API, developers should have to learn as few new concepts as possible to build forms that follow the U.S. Web Design Standards. - Extensibility. The HTML markup generated by the package’s components should be easy to modify and extend, when possible.
- Accessibility. Forms generated by the package should work across a variety of accessible technologies (ATs), such as screen readers and voice recognition systems, with a minimal amount of work on the part of the developer.
Quick start guide¶
Prerequisites¶
This package contains no static files. This means you need to bring in USWDS from somewhere else–use whatever your preferred method from the USWDS developer guide.
You should be able to use any version of USWDS you want, as this package only really depends on the HTML structure and CSS classes of a handful of USWDS widgets.
You’ll also need to make sure the USWDS CSS is included in whatever pages you want to display your forms on.
You’ll need Django 1.11.1 or later.
Your project needs to use either Django’s default
DjangoTemplates
orJinja2
template engine.In a similar vein, your forms need to use either Django’s default
DjangoTemplates
orJinja2
form renderer.Your project needs to use Python 3.
Required settings¶
Add uswds_forms
to your INSTALLED_APPS
setting, e.g.:
INSTALLED_APPS = (
# ...
'uswds_forms',
# ...
)
Jinja2 setup (optional)¶
If you’re using Django’s default template backend, you don’t need
to do any extra configuration. However, if you’re using the
Jinja2
backend,
you might want to add some of this package’s Jinja2 functions to
your Jinja2 environment.
For example, you can create myproject/jinja2.py
with this content:
from jinja2 import Environment
import uswds_forms
def environment(**options):
env = Environment(**options)
env.globals.update({
'fieldset': uswds_forms.fieldset,
})
return env
and in your settings.py
, set the environment
option of the
Jinja2 template engine to point at it, like so:
TEMPLATES = [
# ...
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'environment': 'myproject.jinja2.environment',
}
},
# ...
]
This will allow you to use e.g. the fieldset()
function from any Jinja2 template.
Getting started¶
One way to get started is by visiting the example gallery. It contains a number of examples in increasing complexity. Each example can be tinkered with, and you can also easily view its Python and Django template source code.
If you want to run the example gallery locally, see Developing django-uswds-forms.
Guidelines¶
These guidelines are generally followed by the aforementioned example gallery, so refer to that if you want to see these in action.
If possible, use the
UswdsForm
class for your form. It will make error listings “just work”, and itsas_fieldsets()
can get you by in a pinch; for more fine-grained display of form fields, see the fieldset template tag.In general, Django’s built-in Field classes should work okay out-of-the-box. The major exceptions to these are radios and checkboxes, which use slightly different markup in USWDS than Django’s default, so you’ll want to use our specialized widgets to replace Django’s defaults.
If you want automatic indication of required fields in the style shown in the USWDS name form template, you can set the
required_css_class
attribute on your form to'usa-input-required'
.(Unfortunately, there isn’t currently an easy way to do the inverse of this, where only optional fields are called out.)
API reference¶
Template tags¶
Important
This section is for projects using Django’s default
DjangoTemplates
backend. For
projects using Jinja2, see the Jinja2 functions section.
To use the following template tags, you’ll need to load this package’s custom template tag set in your templates like so:
{% load uswds_forms %}
fieldset
¶
The {% fieldset %}
tag can be used to render a form field using
the <fieldset>
element. The field’s label is also rendered,
along with any associated form errors and help text.
Markup is also added to ensure that screen reader users will have an easy time navigating grouped lists of options.
Sample usage:
{% fieldset my_form.name %}
{% fieldset my_form.address %}
{% fieldset my_form.birthday %}
Jinja2 functions¶
Important
This section is for projects using Django’s
Jinja2
backend. For
projects using Django templates, see the Template tags section.
For details on how to register any of these functions with your Jinja2 environment, see Jinja2 setup (optional).
-
uswds_forms.
fieldset
(field)[source]¶ Render the given bound field as a
<fieldset>
. The field’s label is also rendered, along with any associated form errors and help text.Once added to a Jinja2 environment, this function can be used from Jinja2 templates like so:
{{ fieldset(my_form.name) }} {{ fieldset(my_form.address) }} {{ fieldset(my_form.birthday) }}
Form¶
-
class
uswds_forms.
UswdsForm
[source]¶ This is a subclass of
django.forms.Form
that provides some functionality for rendering USWDS forms. Its constructor takes the exact same arguments, but some defaults are changed:error_class
defaults touswds_forms.UswdsErrorList
, so that errors are formatted nicely.label_suffix
defaults to the empty string, since none of the USWDS example forms have colons after the label names.
-
as_fieldsets
()[source]¶ Like other convenience methods such as
as_p()
andas_table()
, this method renders all the form’s fields as a series of<fieldset>
elements.Under the hood, this just iterates over the form’s fields and renders them via the fieldset template tag, so you can use that if you need more granular control over rendering.
Form fields¶
These fields use the same core field arguments as core Django.
-
class
uswds_forms.
UswdsDateField
(**kwargs)[source]¶ A
django.forms.MultiValueField
for a USWDS-style date. Its value normalizes to a Pythondatetime.date
object.For an example of how this looks in practice, see the USWDS date input example.
-
class
uswds_forms.
UswdsMultipleChoiceField
(**kwargs)[source]¶ This is just a
django.forms.MultipleChoiceField
that uses theUswdsCheckboxSelectMultiple
widget.We’ve provided this field for convenience because the usability of the default
django.forms.SelectMultiple
is so terrible that you’ll probably never want to use it. Burn your select tags!
Widgets¶
All of the following widgets work with
the DjangoTemplates
and
Jinja2
form renderers.
-
class
uswds_forms.
UswdsCheckboxSelectMultiple
[source]¶ This subclass of
django.forms.CheckboxSelectMultiple
styles grouped checkboxes appropriately for USWDS.You can use this in a
django.forms.MultipleChoiceField
to get a list of checkboxes instead of a<select multiple>
element for your choices.For an example of how this looks in practice, see the USWDS checkboxes example.
-
class
uswds_forms.
UswdsDateWidget
[source]¶ A
django.forms.MultiWidget
for a USWDS-style date, with separate number fields for date, month, and year.This widget is used automatically by
uswds_forms.UswdsDateField
, so you probably won’t need to use it directly. However, it can be subclassed in case you need to customize it.-
get_context
(name, value, attrs)[source]¶ Returns the context for the widget’s template. This returns a superset of what’s provided by its superclass’
get_context()
implementation, adding the following keys towidget
:'hint_id'
: The unique id of some hint text showing users an example of what they can enter.'subwidgets'
: This has the same iterable value described in the superclass documentation, but it has been enhanced such that itsyear
,month
, andday
properties are aliases to its entries. Using these aliases can potentially make templates more readable.
-
template_name
= 'uswds_forms/date.html'¶ This is the default template used by the widget, which can be overridden if needed.
-
-
class
uswds_forms.
UswdsRadioSelect
[source]¶ This subclass of
django.forms.RadioSelect
styles radio buttons appropriately for USWDS.You can use this in a
django.forms.ChoiceField
to get a list of radio buttons instead of a<select>
element for your choices.For an example of how this looks in practice, see the USWDS radio buttons example.
Other utilities¶
-
class
uswds_forms.
UswdsErrorList
[source]¶ This is an error list formatter that renders errors in the style used by USWDS forms. For an example of how this makes errors look in practice, see the USWDS text inputs example.
Note that you probably don’t need to use this class directly, as
UswdsForm
uses it by default.For more details on how to use this class, see the Django documentation on customizing the error list format.
Developing django-uswds-forms¶
Important
This section is about developing django-uswds-forms itself, not using it in your Django project. For details on the latter, see the Quick start guide.
First, clone the git repository:
git clone https://github.com/18F/django-uswds-forms
Then create a virtualenv for the project and install development dependencies:
virtualenv -p python3 venv
source venv/bin/activate
pip install -r requirements-dev.txt
Then install django-uswds-forms in development mode:
python setup.py develop
You will also need to download PhantomJS
and put it somewhere on your PATH
, as it’s required by the
test suite.
Running the example gallery app¶
An example Django project provides a integration with django-uswds-forms by presenting a variety of examples alongside their source code. It can be used to manually ensure that everything works as expected.
To use it, run the following from the root of the repository:
cd example
python manage.py migrate
python manage.py runserver
At this point you should be able to visit the locally-hosted project.
Adding new examples¶
To add a new example to the gallery, run:
python manage.py startexample <example-slug>
Where <example-slug>
is a slug for your new example, e.g.
my_cool_example
. The output of the command will tell you
what to do next.
Note that certain kinds of tests are automatically run on all examples:
- A
GET
request is made on the example’s view, and its status code is expected to be 200. - The example is rendered with its Django and Jinja2 template, and both versions are expected to produce the same HTML.
- The example is analyzed by aXe and expected to produce no accessibility violations.
Enabling Jinja2 mode¶
By default, the example gallery app renders all its examples using their Django template source. However, the examples also need to work on Jinja2! To make sure that they do, you’ll want to run the app in Jinja2 mode, which can be done by setting the following environment variable prior to running the app:
export TEMPLATE_ENGINE=jinja2
Running tests¶
You can run all the tests with code coverage:
pytest
You can also ensure that there aren’t any linting errors:
flake8
To run all tests, linters, and other automated QA against all supported runtimes and dependencies, run:
tox
Writing documentation¶
If you want to work on documentation, you can run the development documentation server with:
python setup.py devdocs
Publishing a new release¶
See RELEASE.md for details on publishing a new release.