Opened 16 years ago

Closed 16 years ago

Last modified 13 years ago

#8795 closed (fixed)

unique_together validation fails on model forms that exclude unique fields

Reported by: anihrat@… Owned by: Jacob
Component: Forms Version: dev
Severity: Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Marc Fargas)

i found this bug

when you have model like this:

class FunkcjeProdukt(models.Model):
    funkcja = models.ForeignKey(FunkcjeRodzina)
    produkt = models.ForeignKey(Produkty)
    wartosc = models.CharField(max_length=255)
    class Meta:
        unique_together = ("produkt", "funkcja")

and form from model:

class FunkcjeProduktForm(ModelForm):
    wartosc = forms.CharField(widget=forms.TextInput(attrs={'size':'40','class':'formularz'}))
    class Meta:
        model = FunkcjeProdukt
        exclude=('produkt','funkcja')

end if you want only edit "wartosc" from existing instance:

form_fp = FunkcjeProduktForm(data=request.POST,instance=finst)
if form_fp.is_valid():
       form_fp.save()

error is throw:

KeyError at /cms/r_produkt/8/'produkt'
Request Method:    POST
Request URL:    http://posiflex.com.pl/cms/r_produkt/8/
Exception Type:    KeyError
Exception Value:    'produkt'
Exception Location:    /home/posiflex/django/forms/models.py in validate_unique, line 238

because:
in validate_unique() from django/forms/models.py
line unique_checks = list(self.instance._meta.unique_together[:])
add 'produkt' and 'funkcja' even when this fields in on exclude list

Attachments (1)

django-8795.diff (1.2 KB ) - added by Alex Gaynor 16 years ago.
Fixes problem with the test case to prove it

Download all attachments as: .zip

Change History (13)

comment:1 by Marc Fargas, 16 years ago

Description: modified (diff)

Rewrote Description to hightlight code and not mess with it.

comment:2 by Jacob, 16 years ago

Summary: bug in form validationunique_together validation fails on model forms that exclude unique fields

(Changed title so I'll understand what's going on quicker.)

comment:3 by Julien Phalip, 16 years ago

My call here is "don't do that". You shouldn't save the form if you know the model instance can't be complete. It's actually normal that it fails: the form is valid, the instance is not.

If for example you had a required field your model, but that was excluded in the form. form.save() would also fail, and for a good reason.

I would use form.save(commit=False) in your code instead, and then manually fix the problematic fields.

comment:4 by anonymous, 16 years ago

instance is valid im 100% sure, in this situation first program create instance with "produkt" and "funkcja" complete then in other place user can only modified one field "wartosc" and this traceback show this place:

lookup_kwargs[field_name] = self.cleaned_data[field_name]

this list self.cleaned_data doesnt have 'produkt' key so bug truly exist

by Alex Gaynor, 16 years ago

Attachment: django-8795.diff added

Fixes problem with the test case to prove it

comment:5 by Jacob, 16 years ago

Owner: changed from nobody to Jacob
Status: newassigned
Triage Stage: UnreviewedAccepted

It's not form.save() that's failing; it's form.is_valid(); this is indeed a bug. It's a pretty easy fix; I'll have it done soon.

comment:6 by Jacob, 16 years ago

Er, or maybe I'll just use Alex's fix :)

comment:7 by anonymous, 16 years ago

Alex's fix is working just fine :)

comment:8 by Jacob, 16 years ago

Resolution: fixed
Status: assignedclosed

(In [8854]) Fixed #8795: unique_together validation no longer fails on model forms that exclude fields included in the check. Thanks, Alex Gaynor.

comment:9 by Oliver Andrich, 16 years ago

A question concerning the fix.

Given a model like that:

class Project(models.Model):
    name         = models.CharField(_('Name'), max_length=255)
    creator      = models.ForeignKey(User, verbose_name=_('Ersteller'), related_name='projects') 
    
    class Meta:
        unique_together     = ('name', 'creator')

And a form like that:

class ProjectForm(forms.ModelForm):
    class Meta:
        model   = Project
        fields  = ['name']

form.is_valid() doesn't report the failed constraint, only when I include in the creator field in the fields array too. Seems as the check is broken (or impossible), if only one part of the unique_together constraint is inside the fields list.

Is this a bug or just a case I have to live with, cause it is not solvable?

comment:10 by Julien Phalip, 16 years ago

If you can come up with a test case which is similar to the one added in [8854] and which fails, then yes, you should reopen this ticket.

comment:11 by Malcolm Tredinnick, 16 years ago

In reply to comment:9, the form is valid. The unique_together constraint is only applicable to the model and thus is only going to kick in at save time at the moment. With the model-aware validation work in progress, there'll be an extra step to check the model validity as well, prior to saving so that validation errors there can be handled properly rather than being raised out of save().

comment:12 by Jacob, 13 years ago

milestone: 1.0

Milestone 1.0 deleted

Note: See TracTickets for help on using tickets.
Back to Top