Opened 14 years ago

Closed 14 years ago

#12577 closed (fixed)

BaseGenericInlineFormSet doesn't have save_new() to set the fk instance

Reported by: raffaele.salmaso@… Owned by: nobody
Component: Contrib apps Version: dev
Severity: Keywords:
Cc: raffaele.salmaso@…, apasotti@… Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The behaviour introduced with modelvalidation breaks the generic content type framework

This is the simplest code used to reproduce the bug

# models.py
class PhoneNumber(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    phone = models.CharField(max_length=30)

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

    def __unicode__(self):
        return self.phone

class Contact(models.Model):
    name = models.CharField(max_length=50)
    phones = generic.GenericRelation(PhoneNumber)

    def __unicode__(self):
        return self.name

# admin.py
class PhoneInline(GenericTabularInline):
    model = PhoneNumber
    extra = 1
class ContactAdmin(admin.ModelAdmin):
    inlines = (PhoneInline,)
admin.site.register(Contact, ContactAdmin)

Now trying to save a contact instance with a phone number via the admin interface, results a 404 KeyError

Environment:

Request Method: POST
Request URL: http://localhost:8000/admin/example/genericcontact/1/
Django Version: 1.2 alpha 1
Python Version: 2.6.4
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.admin',
 'django.contrib.comments',
 'example']
Installed Middleware:
('django.middleware.gzip.GZipMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.middleware.doc.XViewMiddleware',
 'django.middleware.transaction.TransactionMiddleware')


Traceback:
File "/home/raf/src/www/simple/site-packages/django/django/core/handlers/base.py" in get_response
  101.                     response = callback(request, *callback_args, **callback_kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/contrib/admin/options.py" in wrapper
  237.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/utils/decorators.py" in __call__
  36.         return self.decorator(self.func)(*args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/utils/decorators.py" in _wrapped_view
  86.                     response = view_func(request, *args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/utils/decorators.py" in __call__
  36.         return self.decorator(self.func)(*args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/views/decorators/cache.py" in _wrapped_view_func
  70.         response = view_func(request, *args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/contrib/admin/sites.py" in inner
  187.             return view(request, *args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/utils/decorators.py" in _wrapped_view
  86.                     response = view_func(request, *args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/db/transaction.py" in _commit_on_success
  295.                     res = func(*args, **kw)
File "/home/raf/src/www/simple/site-packages/django/django/contrib/admin/options.py" in change_view
  883.             if all_valid(formsets) and form_validated:
File "/home/raf/src/www/simple/site-packages/django/django/forms/formsets.py" in all_valid
  317.         if not formset.is_valid():
File "/home/raf/src/www/simple/site-packages/django/django/forms/formsets.py" in is_valid
  238.             if bool(self.errors[i]):
File "/home/raf/src/www/simple/site-packages/django/django/forms/formsets.py" in _get_errors
  212.             self.full_clean()
File "/home/raf/src/www/simple/site-packages/django/django/forms/formsets.py" in full_clean
  254.             self.clean()
File "/home/raf/src/www/simple/site-packages/django/django/forms/models.py" in clean
  412.         self.validate_unique()
File "/home/raf/src/www/simple/site-packages/django/django/forms/models.py" in validate_unique
  435.                     row_data = tuple([form.cleaned_data[field] for field in unique_check])

Exception Type: KeyError at /admin/example/genericcontact/1/
Exception Value: content_type

Attachments (1)

inline.diff (983 bytes ) - added by raffaele.salmaso@… 14 years ago.
reenable the save_new in BaseGenericInlineFormSet

Download all attachments as: .zip

Change History (8)

comment:1 by raffaele.salmaso@…, 14 years ago

With r12206 now tries to save a NULL object_id

Environment:

Request Method: POST
Request URL: http://localhost:8000/admin/example/genericcontact/add/
Django Version: 1.2 alpha 1
Python Version: 2.6.4
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.admin',
 'django.contrib.comments',
 'example']
Installed Middleware:
('django.middleware.gzip.GZipMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.middleware.doc.XViewMiddleware',
 'django.middleware.transaction.TransactionMiddleware')


Traceback:
File "/home/raf/src/www/simple/site-packages/django/django/core/handlers/base.py" in get_response
  101.                     response = callback(request, *callback_args, **callback_kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/contrib/admin/options.py" in wrapper
  237.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/utils/decorators.py" in __call__
  36.         return self.decorator(self.func)(*args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/utils/decorators.py" in _wrapped_view
  86.                     response = view_func(request, *args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/utils/decorators.py" in __call__
  36.         return self.decorator(self.func)(*args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/views/decorators/cache.py" in _wrapped_view_func
  70.         response = view_func(request, *args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/contrib/admin/sites.py" in inner
  187.             return view(request, *args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/utils/decorators.py" in _wrapped_view
  86.                     response = view_func(request, *args, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/db/transaction.py" in _commit_on_success
  295.                     res = func(*args, **kw)
File "/home/raf/src/www/simple/site-packages/django/django/contrib/admin/options.py" in add_view
  781.                     self.save_formset(request, form, formset, change=False)
File "/home/raf/src/www/simple/site-packages/django/django/contrib/admin/options.py" in save_formset
  599.         formset.save()
File "/home/raf/src/www/simple/site-packages/django/django/forms/models.py" in save
  429.         return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/home/raf/src/www/simple/site-packages/django/django/forms/models.py" in save_new_objects
  567.             self.new_objects.append(self.save_new(form, commit=commit))
File "/home/raf/src/www/simple/site-packages/django/django/forms/models.py" in save_new
  413.         return form.save(commit=commit)
File "/home/raf/src/www/simple/site-packages/django/django/forms/models.py" in save
  313.                              fail_message, commit, construct=False)
File "/home/raf/src/www/simple/site-packages/django/django/forms/models.py" in save_instance
  95.         instance.save()
File "/home/raf/src/www/simple/site-packages/django/django/db/models/base.py" in save
  430.         self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/home/raf/src/www/simple/site-packages/django/django/db/models/base.py" in save_base
  519.                     result = manager._insert(values, return_id=update_pk, using=using)
File "/home/raf/src/www/simple/site-packages/django/django/db/models/manager.py" in _insert
  197.         return insert_query(self.model, values, **kwargs)
File "/home/raf/src/www/simple/site-packages/django/django/db/models/query.py" in insert_query
  1345.     return query.get_compiler(using=using).execute_sql(return_id)
File "/home/raf/src/www/simple/site-packages/django/django/db/models/sql/compiler.py" in execute_sql
  730.         cursor = super(SQLInsertCompiler, self).execute_sql(None)
File "/home/raf/src/www/simple/site-packages/django/django/db/models/sql/compiler.py" in execute_sql
  674.         cursor.execute(sql, params)
File "/home/raf/src/www/simple/site-packages/django/django/db/backends/util.py" in execute
  19.             return self.cursor.execute(sql, params)

Exception Type: IntegrityError at /admin/example/genericcontact/add/
Exception Value: null value in column "object_id" violates not-null constraint

comment:2 by Gert Van Gool, 14 years ago

Just wondering why your using a GenericRelation instead of a ManyToManyField ?

comment:3 by Gert Van Gool, 14 years ago

Ignore my reply, just saw what you were doing.

comment:4 by raffaele.salmaso@…, 14 years ago

Has patch: set

ok, tracked what's wrong: new BaseGenericInlineFormSet lacks save_new() to set the fk instance.

by raffaele.salmaso@…, 14 years ago

Attachment: inline.diff added

reenable the save_new in BaseGenericInlineFormSet

comment:5 by anonymous, 14 years ago

Component: UncategorizedContrib apps
Summary: New validation behaviour breaks django.contrib.contenttypes when unique_toghether is usedBaseGenericInlineFormSet doesn't have save_new() to set the fk instance

changed ticket summary to "BaseGenericInlineFormSet doesn't have save_new() to set the fk instance" from "New validation behaviour breaks django.contrib.contenttypes when unique_toghether is used)

comment:6 by anonymous, 14 years ago

Cc: apasotti@… added

comment:7 by jkocherhans, 14 years ago

Resolution: fixed
Status: newclosed

(In [12268]) Fixed #12577. Reverted some changes from [12098] since [12206] made them unneccessary. Also, added a test for using generic inlines with unique_together. Thanks for the report, Raffaele Salmaso.

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