Getting Started *************** .. highlight:: python Sample ====== ``forms.py``:: from django import forms TOPIC_CHOICES = ( ('general', 'General enquiry'), ('bug', 'Bug report'), ('suggestion', 'Suggestion'), ) class ContactForm(forms.Form): topic = forms.ChoiceField(choices=TOPIC_CHOICES) message = forms.CharField(widget=forms.Textarea()) sender = forms.EmailField(required=False) **Note**: See *Forms from Models*, :doc:`models`... ``contact.html`` (normally in ``mysite/templates/app-name/``):: Contact us

Contact us

{% csrf_token %} {{ form.as_table }}

**Note**: See *Custom Look and Feel* below for details on how to construct a custom template rather than using ``form.as_table`` ``app-name/views.py``:: from forms import ContactForm def contact(request): if request.method == 'POST': form = ContactForm(request.POST) else: form = ContactForm() Initial Data ============ Initial data can be set in the form class:: class ContactForm(forms.Form): message = forms.CharField( widget = forms.Textarea(), initial = "Replace with your feedback.") ...or... when the form is created (in ``app-name/views.py``):: def contact(request): if request.method == 'POST': form = ContactForm(request.POST) else: initial = { 'sender': 'user@example.com' } form = ContactForm(initial = initial) Processing ========== ``app-name/views.py``:: from django.core.mail import send_mail from django.http import HttpResponseRedirect from django.shortcuts import render_to_response def contact(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): topic = form.cleaned_data['topic'] message = form.cleaned_data['message'] sender = form.cleaned_data.get('sender', 'noreply@example.com') send_mail( 'Feedback from your site, topic: %s' % topic, message, sender, ['admin@example.com'], fail_silently = True ) return HttpResponseRedirect('contact/thanks/') else: form = ContactForm(initial = {'sender': 'user@example.com'}) return render_to_response('books/contact.html', {'form': form}) **Note**: - The forms framework does more than just validate the data, it also converts it into Python types. - To tell whether a form is bound to valid data, call the ``is_valid()`` method. - In the example above, when using :doc:`../email`, the ``sender`` is not required, so we provide a default. - We have set the Django ``send_mail`` method to ``fail_silently`` because we have not set-up our mail server. - Having sent the feedback email, we'll redirect our user to a static confirmation page. - Redirect After POST: If a user selects *Refresh* on a page that was displayed by a ``POST`` request, that request will be repeated. This can often lead to undesired behavior, such as a duplicate record being added to the database. *Redirect after POST* is a useful pattern that can help avoid this scenario: after a successful ``POST`` has been processed, redirect the user to another page rather than returning HTML directly. Save ---- To update a model before saving, you can follow one of the following patterns:: author = Author(title='Mr') form = PartialAuthorForm(request.POST, instance=author) form.save() form = PartialAuthorForm(request.POST) author = form.save(commit=False) author.title = 'Mr' author.save() Note: See `the save method`_ for further details... Custom Look and Feel ==================== Rather than using ``form.as_table`` (see above) we can build our own custom template:: Contact us

Contact us

{{ form.topic.errors }} {{ form.topic }}
{{ form.message.errors }} {{ form.message }}
{{ form.sender.errors }} {{ form.sender }}

- To construct the control, we just use ``form.`` followed by the name of the field e.g. ``{{ form.topic }}``. - ``{{ form.message.errors }}`` will display as a ``