Opened 12 years ago
Closed 12 years ago
#19408 closed Bug (duplicate)
re-delete on a InlineFormSet object causes untrapped exception
Reported by: | chriscog | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.4 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
If I create a simple two-model application, say the typical Author and Book relationship, and set up any kind of InlineFormSet where an Author lists multiple books, if I set up a circumstance where a book is deleted twice, say open two screens for the Author, delete a book in one screen and "Save", then delete the same book in the other screen and "Save", an exception is raised.
The same scenario can be re-created with one screen by marking the Book to be deleted, then "Save", then hitting the back button, then "Save" again.
This happens both on the Admin screens, or a custom screen using inlineformset_factory.
Code and exception below:
from django.db import models class Author ( models.Model ): name = models.CharField ( max_length=100 ) def __unicode__ ( self ): return self.name class Book ( models.Model ): title = models.CharField ( max_length=100 ) author = models.ForeignKey ( Author ) def __unicode__ ( self ): return self.title
from django.contrib import admin from models import * class BookInline ( admin.TabularInline ): model = Book class AuthorAdmin ( admin.ModelAdmin ): inlines = [ BookInline ] admin.site.register ( Author, AuthorAdmin ) admin.site.register ( Book )
Environment: Request Method: POST Request URL: http://localhost:8000/admin/books/author/1/ Django Version: 1.4.1 Python Version: 2.7.2 Installed Applications: ('django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.admin', 'books') Installed Middleware: ('django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware') Traceback: File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/core/handlers/base.py" in get_response 111. response = callback(request, *callback_args, **callback_kwargs) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/contrib/admin/options.py" in wrapper 366. return self.admin_site.admin_view(view)(*args, **kwargs) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/utils/decorators.py" in _wrapped_view 91. response = view_func(request, *args, **kwargs) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/views/decorators/cache.py" in _wrapped_view_func 89. response = view_func(request, *args, **kwargs) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/contrib/admin/sites.py" in inner 196. return view(request, *args, **kwargs) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/utils/decorators.py" in _wrapper 25. return bound_func(*args, **kwargs) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/utils/decorators.py" in _wrapped_view 91. response = view_func(request, *args, **kwargs) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/utils/decorators.py" in bound_func 21. return func(self, *args2, **kwargs2) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/db/transaction.py" in inner 209. return func(*args, **kwargs) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/contrib/admin/options.py" in change_view 1049. queryset=inline.queryset(request)) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/forms/models.py" in __init__ 697. queryset=qs, **kwargs) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/forms/models.py" in __init__ 424. super(BaseModelFormSet, self).__init__(**defaults) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/forms/formsets.py" in __init__ 50. self._construct_forms() File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/forms/formsets.py" in _construct_forms 115. self.forms.append(self._construct_form(i)) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/forms/models.py" in _construct_form 706. form = super(BaseInlineFormSet, self)._construct_form(i, **kwargs) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/forms/models.py" in _construct_form 451. kwargs['instance'] = self.get_queryset()[i] File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/db/models/query.py" in __getitem__ 190. return self._result_cache[k] Exception Type: IndexError at /admin/books/author/1/ Exception Value: list index out of range
Local vars for the last frame:
k 1 self [<Book: My First Work>]
(I'm going to try and dig into this myself, but wanted to get the bug reported quickly for consideration for 1.5)
Change History (3)
comment:1 by , 12 years ago
comment:2 by , 12 years ago
What might not be clear from the above is that the author had two books, and in both screens I was attempting to delete the 2nd book, that's why 'k' was 1, and 'self' only had a single book in it.
Another scenario using the same trick, but deleting different books, gives different results. Say I have three books, and in both screens I attempt to delete the 2nd one. Since 'k' at this time is 1, but the list likely has two elements in it, we won't get that error. However, another error pops up. An untrapped ValidationError:
Environment: Request Method: POST Request URL: http://localhost:8000/admin/books/author/1/ Django Version: 1.4.2 Python Version: 2.7.2 Installed Applications: ('django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.admin', 'books') Installed Middleware: ('django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware') Traceback: File "/Library/Python/2.7/site-packages/django/core/handlers/base.py" in get_response 111. response = callback(request, *callback_args, **callback_kwargs) File "/Library/Python/2.7/site-packages/django/contrib/admin/options.py" in wrapper 366. return self.admin_site.admin_view(view)(*args, **kwargs) File "/Library/Python/2.7/site-packages/django/utils/decorators.py" in _wrapped_view 91. response = view_func(request, *args, **kwargs) File "/Library/Python/2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func 89. response = view_func(request, *args, **kwargs) File "/Library/Python/2.7/site-packages/django/contrib/admin/sites.py" in inner 196. return view(request, *args, **kwargs) File "/Library/Python/2.7/site-packages/django/utils/decorators.py" in _wrapper 25. return bound_func(*args, **kwargs) File "/Library/Python/2.7/site-packages/django/utils/decorators.py" in _wrapped_view 91. response = view_func(request, *args, **kwargs) File "/Library/Python/2.7/site-packages/django/utils/decorators.py" in bound_func 21. return func(self, *args2, **kwargs2) File "/Library/Python/2.7/site-packages/django/db/transaction.py" in inner 209. return func(*args, **kwargs) File "/Library/Python/2.7/site-packages/django/contrib/admin/options.py" in change_view 1055. self.save_related(request, form, formsets, True) File "/Library/Python/2.7/site-packages/django/contrib/admin/options.py" in save_related 733. self.save_formset(request, form, formset, change=change) File "/Library/Python/2.7/site-packages/django/contrib/admin/options.py" in save_formset 721. formset.save() File "/Library/Python/2.7/site-packages/django/forms/models.py" in save 497. return self.save_existing_objects(commit) + self.save_new_objects(commit) File "/Library/Python/2.7/site-packages/django/forms/models.py" in save_existing_objects 604. pk_value = form.fields[pk_name].clean(raw_pk_value) File "/Library/Python/2.7/site-packages/django/forms/fields.py" in clean 153. value = self.to_python(value) File "/Library/Python/2.7/site-packages/django/forms/models.py" in to_python 988. raise ValidationError(self.error_messages['invalid_choice']) Exception Type: ValidationError at /admin/books/author/1/ Exception Value: [u'Select a valid choice. That choice is not one of the available choices.']
comment:3 by , 12 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
Thanks for the report, but this was already reported (#15574).
Aaaaand... before anyone says anything :) I upgraded to 1.4.2 and re-tested. Same result.