Library Modules

About this document

This document describes the functionality provided by the various python modules in Softwarefabrica Django Forms.

Contents

See also the documentation index.

Modules

extended

The extended module provides backward-compatible replacements for the standard django.forms classes.

Form

softwarefabrica.django.forms.extended.Form is a backward-compatible replacement for django.forms.Form, supporting optional template-based rendering of the form.

Template-based output is enabled only when the optional template_name parameter is specified.

Optional arguments

template_name
Name of the template to use, or a list of template names (if a list is specified, the first template found is utilized). If None, template output is disabled (default is None).
template_loader
Template loader to use (defaults to django.template.loader).

Default templates

A default template is provided as forms/form.html. This template should be adequate for most uses, and can be used as a starting point for further customization. A simplified version of the included forms/form.html templates is:

{% for field in bound_fields %}
    {% include "forms/field.html" %}
{% endfor %}

and forms/field.html is:

{% spaceless %}
<tr{% if field.errors %} class="errors" {% endif %}>
  <th>
    <label for="id_{{ field.name }}"{% if field.field.required %} class="required"{% endif %}>{{ field.label }}{% if field.field.required %} *{% endif %}:</label>
  </th>
  <td>
    {{ field }}
    {% if field.errors %}{{ field.errors }}{% endif %}
    {% if field.help_text %}<p class="helptext">({{ field.help_text }})</p>{% endif %}
  </td>
</tr>
{% endspaceless %}

Example usage:

from softwarefabrica.django.forms.extended import *

>>> class SimpleAuthorForm(Form):
...     name       = forms.CharField(max_length=50)
...     last_name  = forms.CharField(max_length=50)
...     birth_year = forms.IntegerField()
...     active     = forms.BooleanField()

>>> form = SimpleAuthorForm()

>>> print form
...

Then we can enable template-based output by setting `template_name`.

>>> form.template_name = "forms/form.html"

>>> print form
...

Or we can just directly create the form passing `template_name`.

>>> form = SimpleAuthorForm(template_name = "forms/form.html")

>>> print form
...

ModelForm

A compatible replacement for the standard django.forms.ModelForm class, supporting extended features, like field ordering, advanced widgets, templated output.

By default, advanced widgets are used when possible. These include the DateField and DateTimeField replacements with the Javascript calendar, and the ModelChoiceField and ModelMultipleChoiceField replacements with popup interface. These last two are only enabled when the respective model ForeignKey and ManyToManyField fields point to classes which provide the adequate support. Please see the corresponding field documentation for more information.

If you don't want to use the advanced widgets, use the ModelFormStdWidgets class instead.

The arguments described below are the arguments to the Form class built with ModelForm, not to ModelForm itself.

Optional arguments

fieldorder
a list of field names to be used for field ordering when rendering the form.
template_name
Name of the template to use, or a list of template names (if a list is specified, the first template found is utilized). If None, template output is disabled (default is None).
template_loader
Template loader to use (defaults to django.template.loader).

Example usage:

>>> from softwarefabrica.django.forms.extended import *

>>> class BookForm(ModelForm):
...     class Meta:
...         model = Book

>>> BookForm.base_fields.keys()
['title', 'isbn', 'author', 'active']

Let's instantiate the form and see which fields come from the form instance,
and in which order.

>>> form = BookForm()

>>> form.fields.keys()
['title', 'isbn', 'author', 'active']

Now let's try again, but specifying an ordering:

>>> form = BookForm(fieldorder = ['active', 'title', 'author', 'isbn'])

>>> form.fields.keys()
['active', 'title', 'author', 'isbn']

Enable template output

>>> form.template_name = "forms/form.html"

>>> print form
...

Alternatively...

>>> form = BookForm(fieldorder = ['active', 'title', 'author', 'isbn'], template_name = "forms/form.html")

>>> print form
...

ModelFormStdWidgets

Similar to ModelForm but not using advanced widgets, this is a compatible replacement for the standard django.forms.ModelForm class, supporting extended features, like field ordering and templated output.

If you want to use the advanced widgets, use the ModelForm class instead.

The arguments described below are the arguments to the Form class built with ModelFormStdWidgets, not to ModelFormStdWidgets itself.

Optional arguments

fieldorder
a list of field names to be used for field ordering when rendering the form.
template_name
Name of the template to use, or a list of template names (if a list is specified, the first template found is utilized). If None, template output is disabled (default is None).
template_loader
Template loader to use (defaults to django.template.loader).

extended_formfield_cb

This is a form field callback that enables advanced widgets for extended forms. This function is used by the replacement ModelForm class to generate advanced widgets, and can be used with the replacement modelform_factory function to customize the widgets (by passing additional arguments to the callback).

Optional arguments

popup_models
a list of Django db model classes for which popup widgets should be used, when referenced by ForeignKey or ManyToManyField fields. If not specified, all model classes are candidates for the new widgets. Keep in mind that to actually use the extended widgets, the models must implement the proper "protocol" (a set of methods used by the widgets, see the relevant documentation for more information, e.g SelectPopupField).
not_relatedpopup
if True, don't use popup widgets for ForeignKey and ManyToManyField fields.
old_datewidgets
if True, don't use the new popup widgets for DateField and DateTimeField fields.
fallback
an optional formfield callback to be used as a fallback. If not None, the fallback is called with the same arguments received by extended_formfield_cb, and its return value, if not None is passed back to the caller of extended_formfield_cb.

modelform_factory

A replacement for django.forms.models.modelform_factory which uses the extended ModelForm class and mechanism. This function generates dynamically at run-time a form class using the ModelForm mechanism, in the same fashion as would be done normally by the user when declaring in the source a form class deriving from ModelForm.

Optional arguments

form
Base form class to use. Defaults to softwarefabrica.django.forms.extended.ModelForm.
fields
If specified, the field list to use when creating forms.
exclude
If specified, fields that should not appear in the generated forms.
formfield_callback
If specified, the form field callback to use when creating the form class. Default to softwarefabrica.django.forms.extended.extended_formfield_cb. To customize the extended_formfield_cb behaviour, pass a lambda function that perform a custom call to extended_formfield_cb, specifying the desired arguments. See the examples.

Example usage:

>>> from softwarefabrica.django.forms.extended import *

>>> formC = extended.modelform_factory(BookRent, form=ModelForm, formfield_callback=lambda f, cb=extended_formfield_cb: cb(f, old_datewidgets=True))

>>> form = formC()

>>> print form
...

fields

The fields module provides custom Form field classes for the advanced widgets in softwarefabrica.django.forms.widgets.

DateField

A backward-compatible replacement for django.forms.DateField which provides a popup Javascript calendar.

Optional arguments

input_formats
list of input format that the field must accept. Defaults to django.forms.fields.DEFAULT_DATE_INPUT_FORMATS.

To be able to use the popup calendar, you'll need the jscalendar Javascript calendar. A copy is provided with this library in the file jscalendar-1.0.zip. Extract a copy inside your static media javascript directory.

You'll also need to call the calendar Javascript code from your template, for example including the following code fragment inside the <head>...</head> portion:

<!-- calendar -->
<link rel="stylesheet" type="text/css" href="{{ js }}/jscalendar/calendar-win2k-cold-2.css" />
<script type="text/javascript" src="{{ js }}/jscalendar/calendar.js"></script>
<!-- this is translation file - choose your language here -->
<script type="text/javascript" src="{{ js }}/jscalendar/lang/calendar-{% if request.LANGUAGE_CODE %}{{ request.LANGUAGE_CODE }}{% else %}en{% endif %}.js"></script>
<script type="text/javascript" src="{{ js }}/jscalendar/calendar-setup.js"></script>
<!-- /calendar -->

NOTE: we are using the {{ js }} template variable, provided by the softwarefabrica.django.utils.viewshelpers.context_vars context processor.

DateTimeField

A backward-compatible replacement for django.forms.DateTimeField which provides a popup Javascript calendar.

Optional arguments

input_formats
list of input format that the field must accept. Defaults to django.forms.fields.DEFAULT_DATETIME_INPUT_FORMATS.

The same considerations regarding the jscalendar library apply here, as done for DateField.

DateRangeField

A date range field, with popup Javascript calendars.

SelectPopupField

A backward-compatible replacements for ModelChoiceField which uses a popup interface for selecting the related instance. This is usually used as the Form field corresponding to a ForeignKey model field.

There are two conditions to actually use the popup interface:

  1. the page template must load some Javascript support routines, provided by the library as a template (to ease inclusion) in forms/js/Related.js. It's a matter of including the following code fragment inside the <head>...</head> portion:

    <!-- softwarefabrica.django.forms -->
    <script language="javascript" type="text/javascript">
    <!--
    {% include "forms/js/Related.js" %}
    // -->
    </script>
    <!-- /softwarefabrica.django.forms -->
    
  2. the target model must implement a special "protocol", a set of methods used by the corresponding widget to obtain the necessary informations (essentially URLs).

In particular, the target models must implement:

  • the standard method get_absolute_url
  • the class method get_create_url, returning the URL for creating a new instance
  • the method get_edit_url, returning the URL to edit the instance
  • the class method get_list_url, returning the URL for the list view of the instances (typically a generic object_list view, or its equivalent provided by softwarefabrica.django.crud).

Let's see a simple example of a class that can support the popup interface when referenced by a ForeignKey or ManyToManyField:

class Author(models.Model):
    name       = models.CharField(max_length=50)
    last_name  = models.CharField(max_length=50)
    birth_year = models.IntegerField()
    active     = models.BooleanField(default=True)

    def __unicode__(self):
        return u'%s %s' % (self.name, self.last_name)

    class Meta:
        ordering = ['last_name', 'name']

    def get_absolute_url(self):
        return "/authors/%s/" % self.id

    def get_create_url(cls):
        return "/authors/new/"
    get_create_url = classmethod(get_create_url)

    def get_edit_url(self):
        return "/authors/%s/edit" % self.id

    def get_list_url(cls):
        return "/authors/"
    get_list_url = classmethod(get_list_url)

Note that it would be preferable to use named URL patterns and permalink decorators:

def get_absolute_url(self):
    return ('library-author-detail', (), {'object_id': self.id})
get_absolute_url = permalink(get_absolute_url)

def get_create_url(cls):
    return ('library-author-create', (), {})
get_create_url = permalink(get_create_url)
get_create_url = classmethod(get_create_url)

def get_edit_url(self):
    return ('library-author-edit', (), {'object_id': self.id})
get_edit_url = permalink(get_edit_url)

def get_list_url(cls):
    return ('library-author-list', (), {})
get_list_url = permalink(get_list_url)
get_list_url = classmethod(get_list_url)

SelectMultiplePopupField

A backward-compatible replacements for ModelMultipleChoiceField which uses a popup interface for selecting the related instances. This is usually used as the Form field corresponding to a ManyToManyField model field.

To actually use the popup interface, the target model must implement the same special "protocol" described for SelectPopupField above, and include the same Javascript support routines.

RelatedItemField

An alternative field to SelectPopupField, using a different widget. This is usually used as the Form field corresponding to a ForeignKey model field.

Target models for this field need to implement only the get_list_url and get_create_url methods, since the edit button is not provided.

This field uses the same Javascript routines required by SelectPopupField.

widgets

The widgets module provides the advanced Form widgets used by the custom Form field classes in softwarefabrica.django.forms.fields.

DateWidget

Widget used by DateField.

DateTimeWidget

Widget used by DateTimeField.

DateRangeWidget

Widget used by DateRangeField.

SelectPopupWidget

Widget used by SelectPopupField.

SelectMultiplePopupWidget

Widget used by SelectMultiplePopupField.

RelatedItemWidget

Widget used by RelatedItemField.