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).