Opened 7 years ago

Closed 5 years ago

Last modified 5 years ago

#12028 closed Bug (duplicate)

Generic Inline doesn't validate unique_together

Reported by: diverman Owned by:
Component: contrib.contenttypes Version: 1.2
Severity: Normal Keywords: content type generic inline unique validation formset admin modeladmin model
Cc: jvajen@… Triage Stage: Design decision needed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX:

Description

Hello, consider these models:

### models.py
class Tag(models.Model):
    tag = models.CharField(max_length=256)

class TaggedItem(BaseModel):
    tag = models.ForeignKey('Tag')
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField(db_index=True)
    content_object = generic.GenericForeignKey()

    class Meta:
        unique_together = (('content_type', 'object_id', 'tag'),)

class Page(models.Model):
    text = models.TextField()

### admin.py
class TaggedItemInline(generic.GenericTabularInline):
     model = TaggedItem

class PageAdmin(admin.ModelAdmin):
    inlines = ( TaggedItemInline, )

admin.site.register(Tag)
admin.site.register(TaggedItem)
admin.site.register(Page, PageAdmin)

When I edit Page in Admin and try to set non-unique values, it falls into IntegrityError. When I modify TaggedItem in Admin directly, validation of unique_together works fine.

Traceback:
File "/usr/lib/python2.5/site-packages/django/core/handlers/base.py" in get_response
  92.                 response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.5/site-packages/django/contrib/admin/sites.py" in root
  490.                 return self.model_page(request, *url.split('/', 2))
File "/usr/lib/python2.5/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  70.         response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.5/site-packages/django/contrib/admin/sites.py" in model_page
  509.         return admin_obj(request, rest_of_url)
File "/usr/lib/python2.5/site-packages/django/contrib/admin/options.py" in __call__
  1098.             return self.change_view(request, unquote(url))
File "/usr/lib/python2.5/site-packages/django/db/transaction.py" in _commit_on_success
  240.                 res = func(*args, **kw)
File "/usr/lib/python2.5/site-packages/django/contrib/admin/options.py" in change_view
  833.                     self.save_formset(request, form, formset, change=True)
File "/usr/lib/python2.5/site-packages/django/contrib/admin/options.py" in save_formset
  563.         formset.save()
File "/usr/lib/python2.5/site-packages/django/forms/models.py" in save
  522.         return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/usr/lib/python2.5/site-packages/django/forms/models.py" in save_new_objects
  657.             self.new_objects.append(self.save_new(form, commit=commit))
File "/usr/lib/python2.5/site-packages/django/contrib/contenttypes/generic.py" in save_new
  335.         return save_instance(form, new_obj, commit=commit)
File "/usr/lib/python2.5/site-packages/django/forms/models.py" in save_instance
  78.         instance.save()
File "/usr/lib/python2.5/site-packages/django/db/models/base.py" in save
  410.         self.save_base(force_insert=force_insert, force_update=force_update)
File "/usr/lib/python2.5/site-packages/django/db/models/base.py" in save_base
  495.                     result = manager._insert(values, return_id=update_pk)
File "/usr/lib/python2.5/site-packages/django/db/models/manager.py" in _insert
  177.         return insert_query(self.model, values, **kwargs)
File "/usr/lib/python2.5/site-packages/django/db/models/query.py" in insert_query
  1087.     return query.execute_sql(return_id)
File "/usr/lib/python2.5/site-packages/django/db/models/sql/subqueries.py" in execute_sql
  320.         cursor = super(InsertQuery, self).execute_sql(None)
File "/usr/lib/python2.5/site-packages/django/db/models/sql/query.py" in execute_sql
  2369.         cursor.execute(sql, params)
File "/usr/lib/python2.5/site-packages/django/db/backends/util.py" in execute
  19.             return self.cursor.execute(sql, params)

Exception Type: IntegrityError at /admin/web/page/1/
Exception Value: duplicate key value violates unique constraint "tag_taggeditem_content_type_id_key"

Change History (14)

comment:1 Changed 7 years ago by Russell Keith-Magee

Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset
Triage Stage: UnreviewedAccepted

comment:2 Changed 7 years ago by Natalia Bidart

Owner: changed from nobody to Natalia Bidart
Status: newassigned

comment:3 Changed 7 years ago by Natalia Bidart

Owner: Natalia Bidart deleted
Status: assignednew

comment:4 Changed 6 years ago by johndotnet

Version: SVN1.2

this bug is still open, anyone on this ? what happen to nessita ?

comment:5 Changed 6 years ago by Natalia Bidart

I unassigned myself from the bug a while back, currently I don't have enough time to spend in this issue, sorry :-/

comment:6 in reply to:  4 Changed 6 years ago by atli

Version: 1.2SVN

Replying to johndotnet:

this bug is still open, anyone on this ? what happen to nessita ?

why the version change? the current svn-state contains this bug, too

comment:7 Changed 6 years ago by cmarrero

this bug is still open, anyone on this ?

comment:8 Changed 6 years ago by cmarrero

milestone: 1.3
Version: SVN1.2

comment:9 Changed 6 years ago by Jannis

Cc: jvajen@… added
Triage Stage: AcceptedDesign decision needed

The reason for this exception being raised is that both fields content_type and object_id are being excluded from the inline formset as a default. _get_unique_checks() omits the excluded fields from checking for unique constraints and therefore no ValidationError is raised during form validation.

I don't know whether a patch is needed or if the form validation should be done manually in this case.

comment:10 in reply to:  9 Changed 6 years ago by Ramiro Morales

Replying to jnns:

The reason for this exception being raised is that both fields content_type and object_id are being excluded from the inline formset as a default. _get_unique_checks() omits the excluded fields from checking for unique constraints and therefore no ValidationError is raised during form validation.

I don't know whether a patch is needed or if the form validation should be done manually in this case.

See #13091 for what I think is the root cause of this.

comment:11 Changed 6 years ago by Gabriel Hurley

Component: Contrib appscontrib.contenttypes

comment:12 Changed 5 years ago by Julien Phalip

Severity: Normal
Type: Bug

comment:13 Changed 5 years ago by Carl Meyer

Easy pickings: unset
Resolution: duplicate
Status: newclosed

Closing as duplicate of #13091, which seems to have become the canonical bug for this. It's the same root issue.

comment:14 Changed 5 years ago by Jacob

milestone: 1.3

Milestone 1.3 deleted

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