Formularze w Django

Opis systemu generowania i walidacji formularzy dostępnego od Django 1.0.

W pliku z widokami importujemy formularze za pomocą:
from django import forms
Biblioteka składa się z 3 komponentów:
  • Widget - klasa odpowiadająca za kod HTML.
  • Field - klasa odpowiedzialna za walidację, np. pole EmailField sprawdza czy podana wartość jest poprawnym adresem email.
  • Form - zbiór pól, które wiedzą jak się walidować i jak się wyświetlać jak HTML.

Obiekty Form

Podstawową czynnością będzie tworzenie obiektów Form, poprzez dziedziczenie django.forms.Form i podanie zbioru pól, o to przykład:
class TestForm(forms.Form):
	subject = forms.CharField(max_length=100)
	message = forms.CharField()
	sender = forms.EmailField()
W celu otrzymania kodu HTML formularza wystarczy utworzyć obiekt:
f = TestForm()
print f
Wynik:
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>
Zwróć uwagę że nie ma tagów TABLE oraz FORM - ty musisz je dodać w szablonie. Można również otrzymać formularz w postaci listy LI za pomocą metody as_ul() oraz z wykorzystaniem taga P za pomocą as_p().
Przykładowy widok:
def testform(request):
	f = TestForm()
	return render_to_response('content/test.html', {'f1': f, 'f2': f.as_ul(), 'f3': f.as_p()})
Kod szablonu:
<table>
{{ f1 }}
</table>

<br /><hr /><br />

<ul>
{{ f2 }}
</ul>

<br /><hr /><br />

{{ f3 }}
Można podać też początkowe wartości do formularza, wystarczy umieścić je w słowniku podanym jako pierwszy argument obiektu formularza:
class TestForm(forms.Form):
	subject = forms.CharField(max_length=100)
	message = forms.CharField()
	sender = forms.EmailField()

def test_view(request):
	a = TestForm({'subject':'temat', 'message':'wiadomość', 'sender': '1@1.pl'})
	return render_to_response('test.html', {'a':a}, context_instance=RequestContext(request))
Jeżeli nie podany dany dla wszystkich wymaganych pól to wyświetlą się uwagi iż dane pole jest wymagane. Poprawność wprowadzonych możemy sprawdzić za pomocą metody is_valid() zwracającej True/False, a komunikaty wyświetlić za pomocą metody errors() zwracającej słownik o kluczach takich jak nazwy pól. Atrybut cleaned_data zwróci słownik ze "znormalizowanymi" danymi. Przykładowo wprowadzona data w postaci łańcucha stanie się obiektem datetime.date. Atrybut ten istnieje tylko gdy formularz ma poprawne dane (należy wywołać najpierw is_valid()).
def test_view(request):
	a = TestForm({'subject':'temat', 'message':'wiadomość', 'sender': '1@1.pl'})
	print a.is_valid()
	print a.cleaned_data
	return render_to_response('test.html', {'a':a}, context_instance=RequestContext(request))
True
{'message': u'wiadomość', 'sender': u'1@1.pl', 'subject': u'temat'}
By uzyskać dostęp do samych pól formularza wystarczy odwoływać się do pól stosując składnię słownika i nazwy pól jako klucze, np:
def test_view(request):
	a = TestForm({'subject':'temat', 'message':'wiadomość', 'sender': '1@1.pl'})
	print a['sender']
	return render_to_response('test.html', {'a':a}, context_instance=RequestContext(request))

Obsługa formularzy w widokach

Poniżej zaprezentowano przykładowy widok obsługujący formularz i jego walidację:
def test_view(request):
	if request.method == 'POST':
		# dane z POST
		form = TestForm(request.POST)
		if form.is_valid():
			print 'ok'
			# dane poprawne
			return HttpResponseRedirect('/a/')
		else:
			# dane niepoprawne
			return render_to_response('test.html', {'a':form}, context_instance=RequestContext(request))
	else:
		# formularz
		a = TestForm()
		return render_to_response('test.html', {'a':a}, context_instance=RequestContext(request))

Pola formularzy

Każde pole formularza pożna konfigurować za pomocą parametrów:
  • required - domyślnie True, oznacza iż pole jest wymagane
  • label - możemy podać etykietę pola, czyli tekst jaki pojawi się obok pola
  • initial - pozwala określić początkową wartość
  • widget - pozwala określić widget jaki ma zostać użyty do wyświetlenie pola
  • help_text - dodatkowy tekst pomocy
Dostępnych jest szereg typów pól:
  • BooleanField - Pole checkbox na wartości True/False
  • CharField - pole text, dodatkowe argument to max_length i min_length określające maksymalną i minimalną długość wprowadzonego tekstu
  • ChoiceField - pole select przyjmujące argument choices - listę lub tuplę złożoną z 2 elementowych tupli.
  • DateField - pole text walidowane jako data. Argument input_formats umożliwia określenie dopuszczalnych formatów, domyślnie akceptuje:
    '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
    '%b %d %Y', '%b %d, %Y',            # 'Oct 25 2006', 'Oct 25, 2006'
    '%d %b %Y', '%d %b, %Y',            # '25 Oct 2006', '25 Oct, 2006'
    '%B %d %Y', '%B %d, %Y',            # 'October 25 2006', 'October 25, 2006'
    '%d %B %Y', '%d %B, %Y',            # '25 October 2006', '25 October, 2006'
    
  • DateTimeField - pole text walidowane jako data i czas. Domyślnie akceptuje formaty:
    '%Y-%m-%d %H:%M:%S',     # '2006-10-25 14:30:59'
    '%Y-%m-%d %H:%M',        # '2006-10-25 14:30'
    '%Y-%m-%d',              # '2006-10-25'
    '%m/%d/%Y %H:%M:%S',     # '10/25/2006 14:30:59'
    '%m/%d/%Y %H:%M',        # '10/25/2006 14:30'
    '%m/%d/%Y',              # '10/25/2006'
    '%m/%d/%y %H:%M:%S',     # '10/25/06 14:30:59'
    '%m/%d/%y %H:%M',        # '10/25/06 14:30'
    '%m/%d/%y',              # '10/25/06'
  • DecimalField - pole text na liczby zmiennoprzecinkowe. Dodatkowe parametry to max_value, min_value, max_digits (maks. ilość cyfr) i decimal_places (ilość miejsc po przecinku)
  • EmailField - pole text na ares email
  • FileField - pole file na dowolny plik
  • ImageField - pole file na plik graficzny, wymaga PIL
  • IntegerField - pole text na liczby całkowite, dodatkowe argumenty: max_value i min_value
  • MultipleChoiceField - podobne do ChoiceField, lecz umożliwia wybór wielu opcji. Przyjmuje parametr choices.
  • TimeField - pole na czas, domyślnie akceptuje formaty:
    '%H:%M:%S',     # '14:30:59'
    '%H:%M',        # '14:30'
  • URLField - pole na odnośnik URL.

Formularze z modeli

Klasa forms.ModelForm służy do definiowania formularzy generowanych z określonego modelu. Oto przykład:
class CommentForm(forms.ModelForm):
	class Meta:
		# Nazwa modelu
		model = Comment

def show_entry(request, slug):
	# pobranie wpisu
	e = Entry.objects.get(slug=slug)
	# formularz komentarzy
	form = CommentForm()
	if request.POST:
		s = Stripper()
		data = request.POST.copy()
		data['entry'] = str(e.id)
		data['date'] = datetime.now()
		data['text'] = s.strip(data['text'])
		data['author'] = s.strip(data['author'])
		form = CommentForm(data)
		if form.is_valid():
			# zapisanie komentarza do bazy
			form.save()
			form = CommentForm()
	return render_to_response(
		'blog/show.html',
		{'e':e, 'form':form},
		context_instance=RequestContext(request))
Powyższy przykład obsługuje dodawanie komentarzy do wiadomości (Entry). Dodatkowo, jako że nie wyświetlamy pełnego formularza (np. pola relacji do wpisu wyświetlanego jako select wszystkich wiadomości) to musimy przed walidacją danych uzupełnić brakujące dane. W przypadku edycji obiektu do klasy formularza wystarczy podać argument instance z przypisanym obiektem, który ma być edytowany.
blog comments powered by Disqus

Kategorie

Strony