Django

Code

Ticket #8795 (closed: fixed)

Opened 3 months ago

Last modified 3 months ago

unique_together validation fails on model forms that exclude unique fields

Reported by: anihrat@gmail.com Assigned to: jacob
Milestone: 1.0 Component: Forms
Version: SVN Keywords:
Cc: Triage Stage: Accepted
Has patch: 0 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description (Last modified by telenieko)

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

django-8795.diff (1.2 kB) - added by Alex on 09/02/08 08:00:10.
Fixes problem with the test case to prove it

Change History

09/02/08 07:16:37 changed by telenieko

  • needs_better_patch changed.
  • description changed.
  • needs_tests changed.
  • needs_docs changed.

Rewrote Description to hightlight code and not mess with it.

09/02/08 07:38:59 changed by jacob

  • summary changed from bug in form validation to unique_together validation fails on model forms that exclude unique fields.

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

09/02/08 07:48:04 changed by julien

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.

09/02/08 07:59:29 changed 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

09/02/08 08:00:10 changed by Alex

  • attachment django-8795.diff added.

Fixes problem with the test case to prove it

09/02/08 08:00:20 changed by jacob

  • owner changed from nobody to jacob.
  • status changed from new to assigned.
  • stage changed from Unreviewed to Accepted.

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.

09/02/08 08:00:46 changed by jacob

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

09/02/08 08:04:42 changed by anonymous

Alex's fix is working just fine :)

09/02/08 09:20:13 changed by jacob

  • status changed from assigned to closed.
  • resolution set to fixed.

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

09/12/08 04:52:49 changed 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?

09/12/08 05:23:44 changed by julien

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.

09/16/08 20:24:33 changed by mtredinnick

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().


Add/Change #8795 (unique_together validation fails on model forms that exclude unique fields)




Change Properties
Action