I ran into an issue today with the Django Admin and I was wondering if this
was "by design" (in which case I'd like to understand what the rationale
is) or if it was an actual bug that deserves a ticket.
Here's sample code to illustrate the problem.
# models.py
class MasterModel(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return u'%s (Master)' % self.name
class ExternalModel(models.Model):
master = models.ForeignKey(MasterModel, on_delete=models.DO_NOTHING)
class Meta:
managed = False
# admin.py
from django.contrib import admin
import models
admin.site.register(models.MasterModel)
admin.site.register(models.ExternalModel)
When I try to delete a MasterModel object in the Admin, I get the following
exception & traceback:
Environment:
Request Method: POST
Request URL: http://localhost:8000/admin/sample_app/mastermodel/
Django Version: 1.4.2
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django_on_delete_do_nothing_bug.sample_app')
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 "D:\Python27\lib\site-packages\django\core\handlers\base.py" in
get_response
111. response = callback(request, *callback_args,
**callback_kwargs)
File "D:\Python27\lib\site-packages\django\contrib\admin\options.py" in
wrapper
366. return self.admin_site.admin_view(view)(*args,
**kwargs)
File "D:\Python27\lib\site-packages\django\utils\decorators.py" in
_wrapped_view
91. response = view_func(request, *args, **kwargs)
File "D:\Python27\lib\site-packages\django\views\decorators\cache.py" in
_wrapped_view_func
89. response = view_func(request, *args, **kwargs)
File "D:\Python27\lib\site-packages\django\contrib\admin\sites.py" in inner
196. return view(request, *args, **kwargs)
File "D:\Python27\lib\site-packages\django\utils\decorators.py" in _wrapper
25. return bound_func(*args, **kwargs)
File "D:\Python27\lib\site-packages\django\utils\decorators.py" in
_wrapped_view
91. response = view_func(request, *args, **kwargs)
File "D:\Python27\lib\site-packages\django\utils\decorators.py" in
bound_func
21. return func(self, *args2, **kwargs2)
File "D:\Python27\lib\site-packages\django\contrib\admin\options.py" in
changelist_view
1153. response = self.response_action(request,
queryset=cl.get_query_set(request))
File "D:\Python27\lib\site-packages\django\contrib\admin\options.py" in
response_action
908. response = func(self, request, queryset)
File "D:\Python27\lib\site-packages\django\contrib\admin\actions.py" in
delete_selected
35. queryset, opts, request.user, modeladmin.admin_site, using)
File "D:\Python27\lib\site-packages\django\contrib\admin\util.py" in
get_deleted_objects
104. collector.collect(objs)
File "D:\Python27\lib\site-packages\django\contrib\admin\util.py" in collect
155. return super(NestedObjects, self).collect(objs,
source_attr=source_attr, **kwargs)
File "D:\Python27\lib\site-packages\django\db\models\deletion.py" in collect
175. if not sub_objs:
File "D:\Python27\lib\site-packages\django\db\models\query.py" in
__nonzero__
130. iter(self).next()
File "D:\Python27\lib\site-packages\django\db\models\query.py" in
_result_iter
118. self._fill_cache()
File "D:\Python27\lib\site-packages\django\db\models\query.py" in
_fill_cache
892. self._result_cache.append(self._iter.next())
File "D:\Python27\lib\site-packages\django\db\models\query.py" in iterator
291. for row in compiler.results_iter():
File "D:\Python27\lib\site-packages\django\db\models\sql\compiler.py" in
results_iter
763. for rows in self.execute_sql(MULTI):
File "D:\Python27\lib\site-packages\django\db\models\sql\compiler.py" in
execute_sql
818. cursor.execute(sql, params)
File "D:\Python27\lib\site-packages\django\db\backends\util.py" in execute
40. return self.cursor.execute(sql, params)
File "D:\Python27\lib\site-packages\django\db\backends\mysql\base.py" in
execute
114. return self.cursor.execute(query, args)
File "D:\Python27\lib\site-packages\MySQLdb\cursors.py" in execute
174. self.errorhandler(self, exc, value)
File "D:\Python27\lib\site-packages\MySQLdb\connections.py" in
defaulterrorhandler
36. raise errorclass, errorvalue
Exception Type: DatabaseError at /admin/sample_app/mastermodel/
Exception Value: (1146, "Table
'django_bug.sample_app_externalmodeltomaster' doesn't exist")
I would have thought that DO_NOTHING would make Django leave all form of
error checking up to the DBMS, but apparently the Admin still tries to get
the list of children that depend on the object being deleted, ignoring the
DO_NOTHING field. If my understanding of the issue is correct (I apologize
for not spending the time to open up the Django code and figuring this out
for sure myself), the Admin is getting all the dependent objects, then
filters out those for which the ForeignKey is set to DO_NOTHING. Instead, I
would have expected the ExternalModel table in the example above should
simply be excluded from that dependency lookup in the first place...
--
You received this message because you are subscribed to the Google Groups
"Django users" group.
To view this discussion on the web visit
https://groups.google.com/d/msg/django-users/-/yHW7OawWwZQJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-users?hl=en.