A form templating app for Django
Project description
paper-forms
A form templating app for Django
Compatibility
python
>= 3.6django
>= 2.2
Installation
Install the latest release with pip:
pip install paper-forms
Add paper_forms
to your INSTALLED_APPS in settings.py
:
INSTALLED_APPS = (
# ...
"paper_forms",
)
Features
- Jinja2 support.
- django-jinja support.
- Add or replace form field attributes with a template tag.
⚠ WARNING!
paper_forms
does not call the widget'srender()
method. This could be a problem for third-party widgets.
Usage
Let’s create our first Django form.
from django import forms
class ExampleForm(forms.Form):
name = forms.CharField()
age = forms.IntegerField()
No mixins. No third-party classes. Just a simple Django form.
Now, let’s render our form by using the {% field %}
template tag:
{% load paper_forms %}
<form method="post">
{% field form.name %}
{% field form.age %}
</form>
This is exactly the html that you would get:
<form method="post">
<input type="text" name="name" id="id_name" required />
<input type="number" name="age" id="id_age" required />
</form>
As you can see, a {% field form.field %}
template tag behaves
exactly like {{ form.field }}
. This is how you can integrate
paper-forms
with your Django project.
Now, let's add some customization.
Customization
The simplest thing you can do is to add (or replace) attributes to the widget:
{% load paper_forms %}
<form method="post">
{% field form.name placeholder="Enter your name" %}
{% field form.age placeholder="Enter your age" title=form.age.label %}
</form>
Result:
<form method="post">
<input type="text" name="name" id="id_name" placeholder="Enter your name" required />
<input type="number" name="age" title="Age" required placeholder="Enter your age" id="id_age" />
</form>
Note that you cannot specify an attribute with a dashes, like data-src
.
This is because @simple_tag
is quite restrictive and doesn't allow dashes
in kwargs names.
A way to get around this limitation is to use double-underscore.
All double-underscores in {% field %}
arguments are replaced with single dashes:
{% field form.name data__original__name="Name" %}
would render to something like
<input ... data-original-name="Name" />
Override widget templates with Composer
Composer is a tool which gives you full control over form field rendering.
Example:
from django import forms
from paper_forms.composers.base import BaseComposer
class ExampleForm(forms.Form):
name = forms.CharField()
password = forms.CharField()
class Composer(BaseComposer):
widgets = {
"password": forms.PasswordInput
}
template_names = {
"password": "path/to/field_template.html"
}
labels = {
"password": "Enter your password"
}
help_texts = {
"password": "Your password must be 8-20 characters long, "
"contain letters and numbers, and must not contain "
"spaces, special characters, or emoji."
}
As you can see, attributes such as widgets
, labels
and help_texts
are very similar to those
of the ModelForm
's Meta
class. The data specified in the Composer
fields have the highest priority.
There is also the template_names
attribute which allows you to
override a form field templates. Form field template context is a
widget context, extended with label
, errors
and help_text
values. You can add your own data by overriding the
build_widget_context
method in your Composer class.
Template example:
<div class="form-field">
<label for="{{ widget.attrs.id }}">{{ label }}</label>
<!-- include default widget template -->
{% include widget.template_name %}
<!-- show field errors -->
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<!-- show help text -->
{% if help_text %}
<small>{{ help_text }}</small>
{% endif %}
</div>
Create your own Composer
subclass for web frameworks
Example:
from django.forms import widgets
from paper_forms.composers.base import BaseComposer
class Bootstrap4(BaseComposer):
def get_default_template_name(self, widget):
# Overrides the widget template, but has a lower priority
# than the 'template_names' attribute of the Composer class.
if isinstance(widget, widgets.CheckboxInput):
return "paper_forms/bootstrap4/checkbox.html"
else:
return "paper_forms/bootstrap4/input.html"
def get_default_css_classes(self, widget):
# Adds default CSS classes that can be overridden
# in the {% field %} template tag.
if isinstance(widget, widgets.CheckboxInput):
return "form-check-input"
else:
return "form-control"
Settings
-
PAPER_FORMS_DEFAULT_COMPOSER
Default Composer class to be used for any Form that don’t specify a particular composer.
Default:paper_forms.composers.base.BaseComposer
-
PAPER_FORMS_DEFAULT_FORM_RENDERER
The class that renders form widgets.
Default:None
A FORM_RENDERER
problem
If you use django-jinja
(or any other third-party template engine) as your default
template engine, you may also want to use it for your form field templates.
It's a bit tricky because Django's form widgets are rendered using form renderers.
It means that even if your page are rendered with django-jinja
, the form on
that page renders through Django Templates.
You should not change FORM_RENDERER setting, because it can break the admin interface. Most of the third-party widgets are designed for the Django Templates.
Two steps are needed to get around this problem.
-
Make built-in widget templates searcheable.
# settings.py from pathlib import Path from django import forms TEMPLATES = [ { "NAME": "jinja2", "BACKEND": "django_jinja.backend.Jinja2", "DIRS": [ BASE_DIR / "templates", Path(forms.__file__).parent / "jinja2" # <--- ], # ... } ]
-
Use
TemplateSettings
renderer for you forms, or implement your own. There are several ways to do this:-
PAPER_FORMS_DEFAULT_FORM_RENDERER
setting.# settings.py PAPER_FORMS_DEFAULT_FORM_RENDERER = "django.forms.renderers.TemplatesSetting"
-
from django import forms from django.forms.renderers import TemplatesSetting class ExampleForm(forms.Form): default_renderer = TemplatesSetting # ...
-
Composer.renderer
fieldfrom django import forms from paper_forms.composers.base import BaseComposer class ExampleForm(forms.Form): name = forms.CharField() class Composer(BaseComposer): renderer = "django.forms.renderers.TemplatesSetting"
-
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for paper_forms-0.2.2-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 55fd5d4b324fff22d3ece29eb31fcd04aaaa4fe43069f6d9f22beff271d4c5c6 |
|
MD5 | 565f1aa66ed07d9cc1a42ef303f88027 |
|
BLAKE2b-256 | 52d14e4dd9a55fbbe52bcf522bf903a1831a5ce14f7ccc9392b9bf56e4ba3d2f |