Opened 16 years ago

Closed 16 years ago

#8882 closed (fixed)

Inline model formsets break validation for unique and unique_together with foreign keys

Reported by: central@… Owned by: Brian Rosner
Component: Forms Version: 1.0
Severity: Keywords: model-validation
Cc: gabor@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The admin site fails when trying to create two registers (not unique) on a model with unique or unique together fields. It doesn't check for the unique statement and database backend raises an IntegrityError exception like this:

IntegrityError at /admin/myapp/mymodel/add/
(1062, "Duplicate entry '2-1' for key 2")

I haven't checked if the problem exists in "handmade" forms, but in admin site it fails.

Attachments (1)

formset-unique.diff (2.6 KB ) - added by Alex Gaynor 16 years ago.

Download all attachments as: .zip

Change History (17)

comment:1 by anonymous, 16 years ago

Summary: Unique and Unique together in admin inlines is not workingUnique and Unique together in admin inlines are not working

comment:2 by Malcolm Tredinnick, 16 years ago

Can you please construct a small example model that demonstrates the problem you are talking about. That way there's no chance of confusion as to whether we're debugging the problem you are reporting or not.

comment:3 by mrts, 16 years ago

Component: Admin interfaceForms
Triage Stage: UnreviewedAccepted

#8890 is a duplicate. I up this to accepted as I, kratorius from #django-dev IRC, the person behind #8890 and current reporter are hit by this.

Will upload a minimal sample shortly.

comment:4 by mrts, 16 years ago

Also, see #8890 for a sample.

comment:5 by mrts, 16 years ago

Summary: Unique and Unique together in admin inlines are not workingInline model formsets break validation for unique_together with foreign keys

Given the following models.py:

from django.db import models
from django import forms
from django.contrib import admin

class Foo(models.Model):
	foo = models.CharField(max_length=100)

# test for unique
class Bar(models.Model):
	foo = models.ForeignKey(Foo)
	bar = models.CharField(max_length=100, unique=True)

# test for unique_together
class Baz(models.Model):
	foo = models.ForeignKey(Foo)
	baz = models.CharField(max_length=100)

	class Meta:
		unique_together = ("foo", "baz")

class BarInline(admin.StackedInline):
	model = Bar

class BazInline(admin.StackedInline):
	model = Baz

class FooAdmin(admin.ModelAdmin):
	inlines = (BarInline, BazInline)

admin.site.register(Foo, FooAdmin)

Test case 1 -- the database is empty:

  • adding Bar.bar = 'a' twice results in IntegrityError at /admin/uniq/foo/add/ -- column bar is not unique,
  • adding a single Bar.bar = 'a' and consequently adding Baz.baz = 'a' twice results in IntegrityError at /admin/uniq/foo/1/ -- columns foo_id, baz are not unique

Test case 2 -- there is already a Bar with Bar.bar = 'a':

  • adding Bar.bar = 'a' again is correctly validated and Bar with this Bar already exists. displayed,
  • adding a single Bar.bar = 'b' and consequently adding Baz.baz = 'a' twice results in IntegrityError at /admin/uniq/foo/1/ -- columns foo_id, baz are not unique

comment:6 by anonymous, 16 years ago

Summary: Inline model formsets break validation for unique_together with foreign keysInline model formsets break validation for unique and unique_together with foreign keys

comment:7 by Ramiro Morales, 16 years ago

Something the reported in #8890 commented in that ticket that might be of some help: "It appears that the inlineformset_factory helper removes the foreign key field from the produced forms, which prevents validate_unique from actually validating like it is supposed to."

comment:8 by Revil, 16 years ago

This is a short slice of code from django/forms/models.py

    def validate_unique(self):
        from django.db.models.fields import FieldDoesNotExist

        # Gather a list of checks to perform. Since this is a ModelForm, some
        # fields may have been excluded; we can't perform a unique check on a
        # form that is missing fields involved in that check.

The real problem is that the foreign key to the "parent" model in the 1-* relation is missing

comment:9 by anonymous, 16 years ago

Cc: gabor@… added

comment:10 by mrts, 16 years ago

Keywords: model-validation added

comment:11 by Brian Rosner, 16 years ago

Owner: changed from nobody to Brian Rosner
Status: newassigned

by Alex Gaynor, 16 years ago

Attachment: formset-unique.diff added

comment:12 by Brian Rosner, 16 years ago

Resolution: fixed
Status: assignedclosed

(In [9297]) Fixed #8882 -- When a foreign key is among the unique_together fields in an inline formset properly handle it.

comment:13 by Brian Rosner, 16 years ago

(In [9298]) [1.0.X] Fixed #8882 -- When a foreign key is among the unique_together fields in an inline formset properly handle it.

Backport of r9297 from trunk.

comment:14 by mrts, 16 years ago

Resolution: fixed
Status: closedreopened

brosner, the fix is unfortunately insufficient. Alex's patch is also needed, but as that deals with unique checks only, unique_together checks need still to be added to it.

Try the testcase that I've reported above.

I'll examine the code hopefully tomorrow and write a patch.

comment:15 by Fugazi, 16 years ago

This revision causes bug: http://dpaste.com/88174/.
Bug appears when Inline have fieldsets. In the same time, can you add this: http://code.djangoproject.com/ticket/9025 ?
Thank you.

comment:16 by Brian Rosner, 16 years ago

Resolution: fixed
Status: reopenedclosed

I suppose the problem that Alex was patching was indeed described here. There were really *two* issues hidden in this ticket (including all the tickets marked as duplicates). I fixed the one where the foreign key is involved in unique_together didn't work before. Lets not make this more confusing that it needs to be. To isolate the issues lets open new tickets. It will be much easier to track. Alex Gaynor has opened #9493 to track the issue mrts brought up in the reopen. It is a valid issue.

Fugazi, like I said above, lets open a new ticket with *detailed* information about the problem please. #9025 has absolutely nothing to do with any of this.

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