********************************************************
Forms
======
-------------- in form.py
* widget <--- must use this name, otherwise error.
message = forms.charField(widget=forms.Textarea)
---------------- in view.py
* initial <--- must use this name, otherwise error.
form = ProjectForm(initial = {'name'='saju','age'=25)}
----------------- in form.py
custom validation
--------------------
* Django's form system automatically looks for any method whose name starts with "clean_" and
end with the name of a field. if any such method exists , it's called during validation.
* It’s important that we explicitly return the cleaned value for the field at the end of the
method. This allows us to modify the value (or convert it to a different Python type) within our
custom validation method. If we forget the return statement, then None will be returned and
the original value will be lost.
from django import forms
class ProjectForm(forms.Form):
name = forms.CharField(max_length = 4)
estimated_time = forms.CharField(required = False)
message = forms.CharField(widget=forms.Textarea,required = False)
def clean_message(self):
message = self.cleaned_data['message']
num_words = len(message.split())
if num_words < 4:
raise forms.ValidationError("Not enough words")
return message
----------------- in form.py
* cleaned_data <--- must use this name.
It is a list contain all fields in the form (our form class) and its value.
--------------------------- in template
For displat error message
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
--------------------------- in form.py
Specifying Labels
By default, the labels on Django’s autogenerated form HTML are created by replacing under-
scores with spaces and capitalizing the first letter—so the label for the e-mail field is "E-mail".
(Sound familiar? It’s the same simple algorithm that Django’s models use to calculate default
verbose_name values for fields, which we covered in Chapter 5.)
But, as with Django’s models, we can customize the label for a given field. Just use label,
like so:
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
e-mail = forms.EmailField(required=False, label='Your e-mail address')
message = forms.CharField(widget=forms.Textarea)
--------------------in template
{% extends "base.html" %}
{% block title %}Add Project{% endblock %}
{% block content %}
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="{{ action_url }}" method="post">
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit" />
</form>
{% endblock %}
-------------------------
*********************************
Customizing Form Design
=======================
Each field’s widget (<input type="text">, <select>, <textarea>, etc.) can be rendered
individually by accessing {{ form.fieldname }} in the template, and any errors associated
with a field are available as {{ form.fieldname.errors }}. With this in mind, we can construct
a custom template for our contact form with the following template code:
<style type="text/css">
ul.errorlist {
margin: 0;
padding: 0;
}
.errorlist li {
background-color: red;
color: white;
display: block;
font-size: 10px;
margin: 0 0 3px;
padding: 4px 5px;
}
</style>
<html>
<head>
<title>Contact us</title>
</head>
<body>
<h1>Contact us</h1>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="" method="post">
<div class="field">
{{ form.subject.errors }}
<label for="id_subject">Subject:</label>
{{ form.subject }}
</div>
<div class="field">
{{ form.e-mail.errors }}
<label for="id_e-mail">Your e-mail address:</label>
{{ form.e-mail }}
</div>
<div class="field">
{{ form.message.errors }}
<label for="id_message">Message:</label>
{{ form.message }}
</div>
<input type="submit" value="Submit">
</form>
</body>
</html>
{{ form.message.errors }} displays a <ul class="errorlist"> if errors are present and
a blank string if the field is valid (or the form is unbound). We can also treat form.message.
errors as a Boolean or even iterate over it as a list. Consider this example:
<div class="field{% if form.message.errors %} errors{% endif %}">
{% if form.message.errors %}
<ul>
{% for error in form.message.errors %}
<li><strong>{{ error }}</strong></li>
{% endfor %}
</ul>
{% endif %}
<label for="id_message">Message:</label>
{{ form.message }}
</div>
In the case of validation errors, this will add an errors class to the containing <div> and
display the list of errors in an unordered list.
-------------------
********************************************
-------------------- in view, note construction of 'action_url'.
project = get_object_or_404(Project,pk = project_id)
form = ProjectForm(initial = {
'name':project.name
,'estimated_time':project.estimated_time
})
action_url = '/projects/project-edit/%d/'%(project.id)
**************************************
Regular Expression
==================
import re
result = re.match('^\d+:\d{2}$',time)
if result == None:
raise forms.ValidationError("Enter valid time (hour:minute)")
return time
------------------
**************************************
Reverse
-------
* Note: Nor put single quate around "project.id" in args=[project.id].
print reverse('project_detail',args=[project.id])
-------
urlpatterns = patterns('mysite.projects.views',
url(r'^project-detail/(?P<project_id>\d+)/$', 'project_detail', name='project_detail'),
)
------
def project_detail(request, project_id):
project = get_object_or_404(Project, pk=project_id)
return render_to_response('projects/project_detail.html', {'project':project})
------
**************************************
Exceptions
-----------
Caught an exception while rendering: Reverse for 'task_edit' with arguments '(11,)' and keyword arguments '{}' not found.
* This exception occur when number of arguments to view function change.
----------
**************************************