Forms¶
-
class
towel.forms.
BatchForm
(request, queryset, *args, **kwargs) This form class can be used to provide batch editing functionality in list views, similar to Django’s admin actions.
You have to implement your batch processing in the
_context()
method. This method only receives one parameter, a queryset which is already filtered according to the selected items on the list view. Additionally, the current request is available as an attribute of the form instance,self.request
.The method
process(self)
may have the following return values:- A
dict
instance: Will be merged into the template context. - A
HttpResponse
instance: Will be returned directly to the client. - An iterable: The handler assumes successful processing of all objects contained in the iterable.
- Nothing: Nothing happens.
Usage example:
class AddressBatchForm(BatchForm): subject = forms.CharField() body = forms.TextField() def process(self): # Form validation has already been taken care of subject = self.cleaned_data.get('subject') body = self.cleaned_data.get('body') if not (subject and body): return {} sent = 0 for item in self.batch_queryset: send_mail(subject, body, settings.DEFAULT_SENDER, [item.email]) sent += 1 if sent: messages.success(self.request, 'Sent %s emails.' % sent) return self.batch_queryset def addresses(request): queryset = Address.objects.all() batch_form = AddressBatchForm(request, queryset) ctx = {'addresses': queryset} if batch_form.should_process(): result = form.process() if isinstance(result, HttpResponse): return result elif isinstance(result, dict): ctx.update(result) elif hasattr(result, '__iter__'): messages.success(request, _('Processed the following items: %s') % ( ', '.join(force_text(item) for item in result))) return HttpResponseRedirect('.') return render(request, 'addresses.html', ctx)
Template code:
{% load towel_batch_tags %} <form method="post" action="."> <ul> {% for address in addresses %} <li> {% batch_checkbox address.id batch_form %} {{ address }} </li> {% endfor %} </ul> {# Required! Otherwise, ``BatchForm.process`` does nothing. #} <input type="hidden" name="batchform" value="1" /> <table> {{ batch_form }} </table> <button type="submit">Send mail to selected</button> </form>
-
batch_queryset
Returns the queryset containing only items that have been selected for batch processing.
-
clean
() Cleans the batch form fields and checks whether at least one item had been selected.
-
process
() Actually processes the batch form submission. Override this with your own behavior.
Batch forms may return the following types here (they are handled by
ModelView.handle_batch_form
:- A
HttpResponse
: Will be returned directly to the user. - An iterable: A success message will be generated containing all items in the iterable.
- A
-
should_process
() Returns true when the submitted form was the batch form, and the batch form is valid.
- A
-
class
towel.forms.
ModelAutocompleteWidget
(attrs=None, url=None, queryset=None) Model autocompletion widget using jQuery UI Autocomplete
Supports both querysets and JSON-returning AJAX handlers as data sources. Use as follows:
class MyForm(forms.ModelForm): customer = forms.ModelChoiceField(Customer.objects.all(), widget=ModelAutocompleteWidget(url='/customers/search_ajax/'), ) type = forms.ModelChoiceField(Type.objects.all(), widget=ModelAutocompleteWidget(queryset=Type.objects.all()), )
You need to make sure that the jQuery UI files are loaded correctly yourself.
-
class
towel.forms.
MultipleAutocompletionWidget
(attrs=None, queryset=None) You should probably use harvest chosen instead.
-
class
towel.forms.
SearchForm
(data, *args, **kwargs) Supports persistence of searches (stores search in the session). Requires not only the GET parameters but the request object itself to work correctly.
Usage example:
class AddressManager(SearchManager): search_fields = ('first_name', 'last_name', 'address', 'email', 'city', 'zip_code', 'created_by__email') class Address(models.Model): ... objects = AddressManager() class AddressSearchForm(SearchForm): orderings = { '': ('last_name', 'first_name'), # Default 'dob': 'dob', # Sort by date of birth 'random': lambda queryset: queryset.order_by('?'), } is_person = forms.NullBooleanField() def addresses(request): search_form = AddressSearchForm(request.GET, request=request) queryset = search_form.queryset(Address) ctx = { 'addresses': queryset, 'search_form': search_form, } return render(request, 'addresses.html', ctx)
Warning
All fields in the form need to have
required=False
set. Otherwise, form validation would already fail on the first visit on the list page (which would kind of defeat the purpose of a search form).Template code:
<form method="get" action="."> <input type="hidden" name="s" value="1"> <!-- SearchForm search --> <table> {{ search_form }} </table> <button type="submit">Search</button> </form> {% for address in addresses %} ... {% endfor %}
-
always_exclude
= (u's', u'query', u'o') Fields which are always excluded from automatic filtering in
apply_filters
-
apply_filters
(queryset, data, exclude=()) Automatically apply filters
Uses form field names for
filter()
argument construction.
-
apply_ordering
(queryset, ordering=None) Applies ordering if the value in
o
matches a key inself.orderings
. The ordering may also be reversed, in which case theo
value should be prefixed with a minus sign.
-
default
= {} Default field values - used if not overridden by the user
-
fields_iterator
() Yield all additional search fields.
-
o
= None Current ordering
-
orderings
= {} Ordering specification
-
persist
(request) Persist the search in the session, or load saved search if user isn’t searching right now.
-
post_init
(request) Hook for customizations.
-
prepare_data
(data, request) Fill in default values from
default
if they aren’t provided by the user.
-
query
= None Full text search query
-
query_data
() Return a fulltext query and structured data which can be converted into simple filter() calls
-
queryset
(model) Return the result of the search
-
quick_rules
= [] Quick rules, a list of (regex, mapper) tuples
-
s
= None Search form active?
-
safe_cleaned_data
Safely return a dictionary of values, even if search form isn’t valid.
-
searching
() Returns
searching
for use as CSS class if results are filtered by this search form in any way.
-
-
class
towel.forms.
StrippedTextInput
(attrs=None) TextInput
form widget subclass returning stripped contents only
-
class
towel.forms.
StrippedTextarea
(attrs=None) Textarea
form widget subclass returning stripped contents only
-
class
towel.forms.
WarningsForm
(*args, **kwargs) Form subclass which allows implementing validation warnings
In contrast to Django’s
ValidationError
, these warnings may be ignored by checking a checkbox.The warnings support consists of the following methods and properties:
WarningsForm.add_warning(<warning>)
: Adds a new warning messageWarningsForm.warnings
: A list of warnings or an empty list if there are none.WarningsForm.is_valid()
: OverriddenForm.is_valid()
implementation which returnsFalse
for otherwise valid forms with warnings, if those warnings have not been explicitly ignored (by checking a checkbox or by passingignore_warnings=True
tois_valid()
.- An additional form field named
ignore_warnings
is available - this field should only be displayed ifWarningsForm.warnings
is non-emtpy.
-
add_warning
(warning) Adds a new warning, should be called while cleaning the data
-
is_valid
(ignore_warnings=False) is_valid()
override which returnsFalse
for forms with warnings if these warnings haven’t been explicitly ignored
-
towel.forms.
autocompletion_response
(queryset, limit=10) Helper which returns a
HttpResponse
list of instances in a format suitable for consumption by jQuery UI Autocomplete, respectivelytowel.forms.ModelAutocompleteWidget
.
-
towel.forms.
towel_formfield_callback
(field, **kwargs) Use this callback as
formfield_callback
if you want to use stripped text inputs and textareas automatically without manually specifying the widgets. Adds adateinput
class to date and datetime fields too.