Getting started¶
If you just want to see django-pattern-library up and running, have a look at our online demo.
Installation¶
django-pattern-library is available on PyPI. First install it in your Django project:
# With pip,
pip install django-pattern-library
# Alternatively, with Poetry,
poetry add --dev django-pattern-library
Compatibility¶
We support:
- Django 4.2, 5.0, 5.1
- Python 3.9, 3.10, 3.11, 3.12
- Django Templates only, no Jinja support
- Modern “evergreen” desktop and mobile browsers
Configuration¶
Django settings¶
In your Django settings file, add pattern_library
to INSTALLED_APPS
:
INSTALLED_APPS = [
# ...
"pattern_library",
# ...
]
Also add pattern_library.loader_tags
to OPTIONS["builtins"]
into the TEMPLATES
setting:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
"builtins": [
"pattern_library.loader_tags"
],
},
},
]
To see the detailed error pages generated by Django when you have DEBUG = True
in the pattern library, you'll need to make sure you have X_FRAME_OPTIONS
set, or your browser will block the response:
if DEBUG:
X_FRAME_OPTIONS = "SAMEORIGIN"
Be careful only to change this when DEBUG = True
unless you know what you're doing, you risk making your app less secure otherwise!
Pattern library settings¶
Still in Django settings, set the PATTERN_LIBRARY
setting. Here is an example showing the defaults:
PATTERN_LIBRARY = {
# Groups of templates for the pattern library navigation. The keys
# are the group titles and the values are lists of template name prefixes that will
# be searched to populate the groups.
"SECTIONS": (
("components", ["patterns/components"]),
("pages", ["patterns/pages"]),
),
# Configure which files to detect as templates.
"TEMPLATE_SUFFIX": ".html",
# Set which template components should be rendered inside of,
# so they may use page-level component dependencies like CSS.
"PATTERN_BASE_TEMPLATE_NAME": "patterns/base.html",
# Any template in BASE_TEMPLATE_NAMES or any template that extends a template in
# BASE_TEMPLATE_NAMES is a "page" and will be rendered as-is without being wrapped.
"BASE_TEMPLATE_NAMES": ["patterns/base_page.html"],
}
Note the templates in your PATTERN_LIBRARY
settings must be available to template loaders.
URLs¶
Include pattern_library.urls
in your urlpatterns
. Here is an example urls.py
:
from django.apps import apps
from django.urls import include, path
urlpatterns = [
# … Your URLs
]
if apps.is_installed("pattern_library"):
urlpatterns += [
path("pattern-library/", include("pattern_library.urls")),
]
Security
This package isn’t intended for production usage, and hasn’t received extensive security scrutiny.
It is highly recommended to only enable this package in testing environments, for a restricted, trusted audience. One way to do this is to only expose its URLs if apps.is_installed("pattern_library")
, as demonstrated above, and only have the app installed in environment-specific settings.
Alright, now that we got this far, we can navigate to http://localhost:8000/pattern-library/
to see our pattern library! But if we tried to do this now, we would likely get a PatternLibraryEmpty
error – this is expected, as we haven’t added any patterns yet.
Now let’s look at adding our first template!
First pattern¶
Now we’ve done all of the configuration – let’s create a UI component. We’ll use quote-block
as an example, and place it at patterns/components/quote_block/quote_block.html
inside one of our Django apps:
<blockquote class="quote-block block--spacing">
<div class="quote-block__text">
<p class="quote-block__quote">{{ quote }}</p>
{% if attribution %}
<p class="quote-block__attribution">{{ attribution }}</p>
{% endif %}
</div>
</blockquote>
Base template¶
We additionally need to customize a base template, so the standalone component can be rendered within a page with CSS. This is what the PATTERN_BASE_TEMPLATE_NAME
setting is for. As a separate template in patterns/base.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Base</title>
</head>
<body>
{% block content %}
{# pattern_library_rendered_pattern is where the pattern library will inject the rendered pattern. #}
{{ pattern_library_rendered_pattern }}
{% endblock %}
</body>
</html>
quote_block
should now appear in the pattern library UI menu! But the template doesn’t display anything – we additionally need to provide it with test data.
Component data¶
We can provide context and tags overrides for our new component by creating a quote_block.yaml
YAML file alongside the HTML, at patterns/components/quote_block/quote_block.yaml
in our example. You can use either .yaml
or .yml
as the file extension.
context:
quote: What is love?
attribution: Haddaway
We could also provide it with a custom name:
name: Quote Block
context:
quote: What is love?
attribution: Haddaway
And that’s it! Our quote_block
should finally appear in the pattern library, along with its rendering with this mock data.