RkBlog

Hardware, programming and astronomy tutorials and reviews.

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:

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: Dostępnych jest szereg typów pól:

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

14 July 2008;

Comment article