from django.forms.formsets import * from django.forms.util import ValidationError from django.utils.translation import ugettext as _ from django.forms.formsets import TOTAL_FORM_COUNT from django.forms.formsets import INITIAL_FORM_COUNT from django.forms.formsets import DELETION_FIELD_NAME from django.forms.formsets import ORDERING_FIELD_NAME from django.forms.formsets import formset_factory as django_formset_factory from django.forms.forms import Form from fields import IntegerField, BooleanField from widgets import Media, HiddenInput from django.forms.formsets import BaseFormSet __all__ = ('BaseFormSet', 'all_valid') class ManagementForm(Form): """ Changed ManagementForm. It is using the dojango form fields. """ def __init__(self, *args, **kwargs): self.base_fields[TOTAL_FORM_COUNT] = IntegerField(widget=HiddenInput) self.base_fields[INITIAL_FORM_COUNT] = IntegerField(widget=HiddenInput) Form.__init__(self, *args, **kwargs) class BaseFormSet(BaseFormSet): """ Overwritten BaseFormSet. Basically using the form extension of dojango. """ def _dojango_management_form(self): """Attaching our own ManagementForm""" if self.data or self.files: form = ManagementForm(self.data, auto_id=self.auto_id, prefix=self.prefix) if not form.is_valid(): raise ValidationError('ManagementForm data is missing or has been tampered with') else: is_dojo_1_0 = getattr(self, "_total_form_count", False) # this is for django versions before 1.1 initial = { TOTAL_FORM_COUNT: is_dojo_1_0 and self._total_form_count or self.total_form_count(), INITIAL_FORM_COUNT: is_dojo_1_0 and self._initial_form_count or self.initial_form_count() } form = ManagementForm(auto_id=self.auto_id, prefix=self.prefix, initial=initial) return form dojango_management_form = property(_dojango_management_form) def __getattribute__(self, anatt): """This is the superhack for overwriting the management_form property of the super class using a newly defined ManagementForm. In Django this property should've be defined lazy: management_form = property(lambda self: self._management_form()) """ if anatt == 'management_form': anatt = "dojango_management_form" return super(BaseFormSet, self).__getattribute__(anatt) def add_fields(self, form, index): """Using the dojango form fields instead of the django ones""" is_dojo_1_0 = getattr(self, "_total_form_count", False) if self.can_order: # Only pre-fill the ordering field for initial forms. # before django 1.1 _total_form_count was used! if index < (is_dojo_1_0 and self._total_form_count or self.total_form_count()): form.fields[ORDERING_FIELD_NAME] = IntegerField(label=_(u'Order'), initial=index+1, required=False) else: form.fields[ORDERING_FIELD_NAME] = IntegerField(label=_(u'Order'), required=False) if self.can_delete: form.fields[DELETION_FIELD_NAME] = BooleanField(label=_(u'Delete'), required=False) def formset_factory(*args, **kwargs): """Formset factory function that uses the dojango BaseFormSet""" kwargs["formset"] = BaseFormSet return django_formset_factory(*args, **kwargs)