Plain is headed towards 1.0! Subscribe for development updates →

 1# Forms
 2
 3**HTML form handling and validation.**
 4
 5The `Form` and `Field` classes help output, parse, and validate form data from an HTTP request. Unlike other frameworks, the HTML inputs are not rendered automatically, though there are some helpers for you to do your own rendering.
 6
 7With forms, you will typically use one of the built-in view classes to tie everything together.
 8
 9```python
10from plain import forms
11from plain.views import FormView
12
13
14class ContactForm(forms.Form):
15    email = forms.EmailField()
16    message = forms.CharField()
17
18
19class ContactView(FormView):
20    form_class = ContactForm
21    template_name = "contact.html"
22```
23
24Then in your template, you can render the form fields.
25
26```html
27{% extends "base.html" %}
28
29{% block content %}
30
31<form method="post">
32    {{ csrf_input }}
33
34    <!-- Render general form errors -->
35    {% for error in form.non_field_errors %}
36    <div>{{ error }}</div>
37    {% endfor %}
38
39    <div>
40        <label for="{{ form.email.html_id }}">Email</label>
41        <input
42            required
43            type="email"
44            name="{{ form.email.html_name }}"
45            id="{{ form.email.html_id }}"
46            value="{{ form.email.value }}">
47
48        {% if form.email.errors %}
49        <div>{{ form.email.errors|join(', ') }}</div>
50        {% endif %}
51    </div>
52
53    <div>
54        <label for="{{ form.message.html_id }}">Message</label>
55        <textarea
56            required
57            rows="10"
58            name="{{ form.message.html_name }}"
59            id="{{ form.message.html_id }}">{{ form.message.value }}</textarea>
60
61        {% if form.message.errors %}
62        <div>{{ form.message.errors|join(', ') }}</div>
63        {% endif %}
64    </div>
65
66    <button type="submit">Submit</button>
67</form>
68
69{% endblock %}
70```
71
72With manual form rendering, you have full control over the HTML classes, attributes, and JS behavior. But in large applications the form rendering can become repetitive. You will often end up re-using certain patterns in your HTML which can be abstracted away using Jinja [includes](https://jinja.palletsprojects.com/en/stable/templates/#include), [macros](https://jinja.palletsprojects.com/en/stable/templates/#macros), or [plain.elements](/plain-elements/README.md).