Forms
Pegasus ships with some extensions to Django forms to integrate with different CSS frameworks and add some extensions.
The form_tags
module
Section titled “The form_tags module”You can use default Django form rendering for forms, but if you want all the built-in style support,
you should instead use the utilities in the form_tags
module.
To use it, first include form_tags
in any Django template file:
{% load form_tags %}
Then, you can render a form using the render_form_fields
template tag.
Here is a basic example:
<form method="post"> {% csrf_token %} {{ form.non_field_errors }} {% render_form_fields form %} <div class="mt-2"> <button class="pg-button-primary" type="submit">{% translate "Submit Form" %}</button> </div></form>
You can also render individual fields using render_field
:
<form method="POST" action="{% url 'account_change_password' %}" class="password_change"> {% csrf_token %} {{ form.non_field_errors }} {% render_field form.username %} {% render_field form.password %} <div class="mt-2"> <input class="pg-button-primary" type="submit" value="{% translate 'Login' %}"> </div></form>
Dynamic forms with Alpine.js
Section titled “Dynamic forms with Alpine.js”Added in version 2023.6
The form rendering helpers also support adding attributes, which can be useful to add Alpine.js to make a form more dynamic.
For example, you can bind a form value to an alpine model by passing it in attrs
like this:
class ExampleFormAlpine(forms.Form): YES_NO_OTHER = ( ("yes", gettext("Yes")), ("no", gettext("No")), ("other", gettext("Other")), ) like_django = forms.ChoiceField( label=gettext("Do you like Django?"), choices=YES_NO_OTHER, widget=forms.Select(attrs={"x-model": "likeDjango"}), # this line will bind the value to an alpine model )
Then in the HTML template you have to add an alpine model to the form:
<form method="post" x-data="{ likeDjango: '{{ form.like_django.data|default:"yes" }}', styleValue: '{{ form.styled_options.data|default:"regular" }}' }"> <!-- other fields here --> {% render_field form.like_django %} <!-- this will bind to `likeDjango` above -->
The render_field
tags support two special syntaxes to make using alpine easier:
- Any attribute starting with
x
will be automatically converted tox-
. - Double underscores (
__
) will be replaced with colons (:
).
The following example alpine form and template (which also ship with Pegasus, available at http://localhost:8000/pegasus/forms/alpine/) demonstrate this usage, including hiding/showing a field based on the value of another field, rendering field values in labels, and changing the style of a field based on its value.
Django form class:
class ExampleFormAlpine(forms.Form): YES_NO_OTHER = ( ("yes", gettext("Yes")), ("no", gettext("No")), ("other", gettext("Other")), ) STYLES = ( ("regular", gettext("Normal")), ("success", gettext("Success")), ("danger", gettext("Danger")), ) like_django = forms.ChoiceField( label=gettext("Do you like Django?"), help_text=gettext("Try choosing 'other' to see unhiding a form field based on a value."), choices=YES_NO_OTHER, widget=forms.Select(attrs={"x-model": "likeDjango"}), ) like_django_other = forms.CharField(label=gettext("Please specify more details about your answer.")) styled_options = forms.ChoiceField( label=gettext("Styled Options"), help_text=gettext("Try picking an option to see how you can style a component based on its value."), choices=STYLES, widget=forms.Select(attrs={"x-model": "styleValue"}), )
Django template:
<form method="post" x-data="{ likeDjango: '{{ form.like_django.data|default:"yes" }}', styleValue: '{{ form.styled_options.data|default:"regular" }}' }"> {% csrf_token %} {% render_field form.like_django %} {% render_field form.like_django_other xshow="likeDjango === 'other'" xcloak='True' %} {% render_field form.styled_options xbind__class="'pg-bg-' + styleValue" %} <p class="mt-4">You can also use alpine to display selected values. <em> Like Django: <strong x-text="likeDjango"></strong>, Style: <strong x-text="styleValue"></strong> </em> </p> <input type="submit" value="Save Data" class="pg-button-secondary mt-2"></form>