Search code examples
djangoformsdjango-modelsinline-formset

Django: Saving with "Unique Together" and Deleting objects via inlineformset causes error pages


Sorry if this is a simple fix, I am having 2 issues with my inlineformset:

  1. Saving an invalid object (does not meet unique together requirement) throws an error page rather than displaying the errors in the form.

    At one point I had my errors displaying correctly when saving an invalid object, but when I tried to save a valid object I would get an error saying that membership.department was null. Which is why I put the "for instance in instances" but now I get this new issue of not displaying errors when saving a invalid object.

  2. I have the same issue when deleting a valid object. The object gets deleted as it should, but I still get an error page...

I am at a lost.

When saving invalid objects I get:

The Membership could not be created because the data didn't validate.

When deleting valid objects I get:

[u'Select a valid choice. That choice is not one of the available choices.']

MODEL:

class Membership(models.Model):
    project = models.ForeignKey(Project)
    department = models.ForeignKey(Department)
    employee = models.ForeignKey(Employee)
    role = models.ManyToManyField(Role, blank=True, null=True)
    class Meta:
        unique_together = (("project", "employee",),)

VIEW.py

def employee_edit(request, employee_id):
    i = get_object_or_404(Employee, pk=employee_id)
    MembershipForm = make_membership_form(i)
    MembershipFormSet = inlineformset_factory(Employee, Membership, exclude='department', extra=1, form=MembershipForm)
    if request.method == "POST":
        f = MembershipFormSet(request.POST, instance=i)
        if f.is_valid():
            instances = f.save(commit=False)
            for instance in instances:
                instance.department = i.department
                instance.save()
            f.save_m2m()
            return render_to_response('dbtest/edit.html', {'item': i, 'formset': f, }, context_instance=RequestContext(request))
    else:
        f = MembershipFormSet(instance=i)
    return render_to_response('dbtet/edit.html', {'item': i, 'formset': f, }, context_instance=RequestContext(request))

def make_membership_form(i):
    class MembershipForm(forms.ModelForm):
        project = forms.ModelChoiceField(queryset=Project.objects.filter(department=i.department))
        class Meta:
            model = Membership
            exclude = ('department', 'employee')
            unique_together = (("project", "employee",),)
    return MembershipForm

Solution

  • The first error message is pretty straight forward.

    The Membership could not be created because the data didn't validate.
    

    You are saving the formset without checking first that it's valid. You should only call save if formset.is_valid() is true. Have another look at my answer to your previous question