Code

Opened 5 years ago

Closed 3 years ago

Last modified 3 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"

Attachments (0)

Change History (14)

comment:1 Changed 4 years ago by russellm

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

comment:2 Changed 4 years ago by nessita

  • Owner changed from nobody to nessita
  • Status changed from new to assigned

comment:3 Changed 4 years ago by nessita

  • Owner nessita deleted
  • Status changed from assigned to new

comment:4 follow-up: Changed 4 years ago by johndotnet

  • Version changed from SVN to 1.2

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

comment:5 Changed 4 years ago by nessita

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 4 years ago by atli

  • Version changed from 1.2 to SVN

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 4 years ago by cmarrero

this bug is still open, anyone on this ?

comment:8 Changed 3 years ago by cmarrero

  • milestone set to 1.3
  • Version changed from SVN to 1.2

comment:9 follow-up: Changed 3 years ago by jnns

  • Cc jvajen@… added
  • Triage Stage changed from Accepted to Design 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 3 years ago by ramiro

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 3 years ago by gabrielhurley

  • Component changed from Contrib apps to contrib.contenttypes

comment:12 Changed 3 years ago by julien

  • Severity set to Normal
  • Type set to Bug

comment:13 Changed 3 years ago by carljm

  • Easy pickings unset
  • Resolution set to duplicate
  • Status changed from new to closed

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

comment:14 Changed 3 years ago by jacob

  • milestone 1.3 deleted

Milestone 1.3 deleted

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.