Here is what I came up with. I had to override ModelForm as well to
get rid of validation errors in emptied forms. This solution works in
my use case where I only have CharFields and IntegerFields. It's not
as simple as I had wished. Can it be?

class DeleteIfEmptyModelForm(ModelForm):
    """
    A ModelForm which marks itself valid and empty if all visible
fields are
    blank or all-whitespace.
    """
    def full_clean(self):
        if not self.is_bound:
            return
        if not self.is_empty():
            return super(DeleteIfEmptyModelForm, self).full_clean()

    def is_empty(self):
        self.cleaned_data = {}
        if not hasattr(self, '_empty'):
            self._empty = True
            for boundfield in self:
                field = self.fields[boundfield.name]
                value = field.widget.value_from_datadict(
                    self.data, self.files, self.add_prefix
(boundfield.name))
                if not boundfield.is_hidden and boundfield.name !=
DELETION_FIELD_NAME and value is not None and str(value).strip():
                    self._empty = False
                    break
                try:
                    clean_value = field.clean(value)
                except ValidationError:
                    clean_value = ''
                self.cleaned_data[boundfield.name] = clean_value
        return self._empty

class DeleteIfEmptyInlineFormSet(BaseInlineFormSet):
    """
    Modified version of django.forms.models.BaseInlineFormSet for
allowing
    deleting objects by emptying their visible fields instead of
checking the
    delete checkbox.

    Not overriding _get_deleted_forms() since it doesn't seem to be
used in my
    use case.
    """
    def save_existing_objects(self, commit=True):
        """Only one small change here, see comment below"""
        self.changed_objects = []
        self.deleted_objects = []
        if not self.get_queryset():
            return []
        existing_objects = {}
        for obj in self.get_queryset():
            existing_objects[obj.pk] = obj
        saved_instances = []
        for form in self.initial_forms:
            obj = existing_objects[form.cleaned_data
[self._pk_field.name]]
            # the change is on this line:
            if self.can_delete and (form.cleaned_data
[DELETION_FIELD_NAME] or form.is_empty()):
                self.deleted_objects.append(obj)
                obj.delete()
            else:
                if form.changed_data:
                    self.changed_objects.append((obj,
form.changed_data))
                    saved_instances.append(self.save_existing(form,
obj, commit=commit))
                    if not commit:
                        self.saved_forms.append(form)
        return saved_instances

    def add_fields(self, form, index):
        """Override delete field and make it hidden."""
        super(DeleteIfEmptyInlineFormSet, self).add_fields(form,
index)
        form.fields[DELETION_FIELD_NAME].widget = forms.HiddenInput()

# usage:
formset_class = forms.models.inlineformset_factory(
    parent_model, model,
    form=DeleteIfEmptyModelForm, formset=DeleteIfEmptyInlineFormSet)
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to