-
-
Notifications
You must be signed in to change notification settings - Fork 302
Description
Hi,
I have an issue in django-polymorphic when deleting models from django-admin.
Models are defined as below
class Farm(models.Model):
class Meta:
pass
class Animal(PolymorphicModel):
farm = models.ForeignKey('Farm', on_delete=models.CASCADE)
name = models.CharField(max_length=100)
class Meta:
pass
class Dog(Animal):
dog_param = models.CharField(max_length=100)
class Meta:
pass
class Cat(Animal):
cat_param = models.CharField(max_length=100)
class Meta:
passNow I am creating a Farm object with both a Dog and a Cat (problem doesn't appear if all polymorphic related objects are of the same sub-class.
When trying to delete the Farm object in admin, I get the below hierarchy
- Farm: Farm number 19
- Dog: 37 - dog
- Cat: 38 - cat
- Animal: 37 - dog
- Animal: 38 - cat
And when confirming the deletion, I get the error below
Internal Server Error: /admin/farming/farm/
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py", line 541, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py", line 149, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/cache.py", line 57, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/sites.py", line 244, in inner
return view(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py", line 67, in _wrapper
return bound_func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py", line 149, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py", line 63, in bound_func
return func.__get__(self, type(self))(*args2, **kwargs2)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py", line 1512, in changelist_view
response = self.response_action(request, queryset=cl.get_queryset(request))
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py", line 1245, in response_action
response = func(self, request, queryset)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/actions.py", line 49, in delete_selected
queryset.delete()
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 600, in delete
deleted, _rows_count = collector.delete()
File "/usr/local/lib/python2.7/dist-packages/django/db/models/deletion.py", line 308, in delete
for model, instances in six.iteritems(self.data):
File "/usr/local/lib/python2.7/dist-packages/django/db/transaction.py", line 223, in __exit__
connection.commit()
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/base/base.py", line 242, in commit
self._commit()
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/base/base.py", line 211, in _commit
return self.connection.commit()
File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py", line 95, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/base/base.py", line 211, in _commit
return self.connection.commit()
IntegrityError: update or delete on table "farming_animal" violates foreign key constraint "farming_cat_animal_ptr_id_77dae4b8_fk_farming_animal_id" on table "farming_cat"
DETAIL: Key (id)=(38) is still referenced from table "farming_cat".I tracked the problem down to be a problem in the deletion Collector class where related object to Farm (i.e. Animal) are of the sub-classes either Dog or Cat. So in the case above, we try to delete the Cat object from the Dog table.
I solved my problem by using the _base_manager property of the Model class . And referring to a non polymorphic object manager like below
class Animal(PolymorphicModel):
instance = models.ForeignKey('Farm', on_delete=models.CASCADE)
name = models.CharField(max_length=100)
_base_manager = models.Manager()
class Meta:
passNow when trying to delete the Farm object in admin I get the correct hierarchy
- Farm: Farm number 19
- Animal: Fix model subclass ___ selector for abstract/proxy models #37 - dog
- Animal: Simplify add_type_form.html #38 - cat
- Cat: Simplify add_type_form.html #38 - cat
I am using the below
psql 9.3.11
python 2.7.6
django 1.9.8
django-polymorphic 0.9.2My thought would be to add _base_manager = models.Manager() in the django-polymorphic PolymorphicModel. What do you guy think about this ?
Thanks,
Theo