The form is defined in HTML as a collection of elements inside <form>
…</form>
tags, containing at least one input element of type=”submit”.
<form action="/team_name_url/" method="post">
<label for="team_name">Enter name: </label>
<input id="team_name" type="text" name="name_field" value="Default name for team.">
<input type="submit" value="OK">
</form>
The form attributes define the HTTP method used to send the data and the destination of the data on the server (action):
A process flowchart of how Django handles form requests is shown below, starting with a request for a page containing a form
the main things that Django’s form handling does are:
Declaring a Form
from django import forms
class RenewBookForm(forms.Form):
renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).")
The arguments that are common to most fields are listed below:
Update forms.py file so it looks like this:
import datetime
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
class RenewBookForm(forms.Form):
renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).")
def clean_renewal_date(self):
data = self.cleaned_data['renewal_date']
# Check if a date is not in the past.
if data < datetime.date.today():
raise ValidationError(_('Invalid date - renewal in past'))
# Check if a date is in the allowed range (+4 weeks from today).
if data > datetime.date.today() + datetime.timedelta(weeks=4):
raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead'))
# Remember to always return the cleaned data.
return data
urlpatterns += [
path('book/<uuid:pk>/renew/', views.renew_book_librarian, name='renew-book-librarian'),
]
import datetime
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect
from django.urls import reverse
from catalog.forms import RenewBookForm
def renew_book_librarian(request, pk):
book_instance = get_object_or_404(BookInstance, pk=pk)
if request.method == 'POST':
form = RenewBookForm(request.POST)
if form.is_valid():
book_instance.due_back = form.cleaned_data['renewal_date']
book_instance.save()
return HttpResponseRedirect(reverse('all-borrowed') )
else:
proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3)
form = RenewBookForm(initial={'renewal_date': proposed_renewal_date})
context = {
'form': form,
'book_instance': book_instance,
}
return render(request, 'catalog/book_renew_librarian.html', context)
First, we import our form (RenewBookForm) and a number of other useful objects/methods used in the body of the view function:
The final view is therefore as shown below. Please copy this into the bottom of locallibrary/catalog/views.py.
import datetime
from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect
from django.urls import reverse
from catalog.forms import RenewBookForm
@login_required
@permission_required('catalog.can_mark_returned', raise_exception=True)
def renew_book_librarian(request, pk):
book_instance = get_object_or_404(BookInstance, pk=pk)
if request.method == 'POST':
form = RenewBookForm(request.POST)
# Check if the form is valid:
if form.is_valid():
# process the data in form.cleaned_data as required (here we just write it to the model due_back field)
book_instance.due_back = form.cleaned_data['renewal_date']
book_instance.save()
return HttpResponseRedirect(reverse('all-borrowed') )
else:
proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3)
form = RenewBookForm(initial={'renewal_date': proposed_renewal_date})
context = {
'form': form,
'book_instance': book_instance,
}
return render(request, 'catalog/book_renew_librarian.html', context)
Template:
we can access a number of separate items for the renewal_date field:
from django.forms import ModelForm
from catalog.models import BookInstance
class RenewBookModelForm(ModelForm):
class Meta:
model = BookInstance
fields = ['due_back']