Opened 10 years ago

Closed 10 years ago

Last modified 7 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: master
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

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

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

error is throw:

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

in validate_unique() from django/forms/
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 10 years ago.
Fixes problem with the test case to prove it

Download all attachments as: .zip

Change History (13)

comment:1 Changed 10 years ago by Marc Fargas

Description: modified (diff)

Rewrote Description to hightlight code and not mess with it.

comment:2 Changed 10 years ago by Jacob

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 Changed 10 years ago by Julien Phalip

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. would also fail, and for a good reason.

I would use in your code instead, and then manually fix the problematic fields.

comment:4 Changed 10 years ago by anonymous

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

Changed 10 years ago by Alex Gaynor

Attachment: django-8795.diff added

Fixes problem with the test case to prove it

comment:5 Changed 10 years ago by Jacob

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

It's not 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 Changed 10 years ago by Jacob

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

comment:7 Changed 10 years ago by anonymous

Alex's fix is working just fine :)

comment:8 Changed 10 years ago by Jacob

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 Changed 10 years ago by oliverandrich

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 Changed 10 years ago by Julien Phalip

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 Changed 10 years ago by Malcolm Tredinnick

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 Changed 7 years ago by Jacob

milestone: 1.0

Milestone 1.0 deleted

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