4

I'm currently maintaining a legacy system while a new system is brought up. I noticed recently that I get a timeout when trying to delete certain objects from a specific model. I've tracked this down to being related to the following question which has an accepted answer: Django admin hangs (until timeout error) for a specific model when trying to edit/create

The problem I'm having is that the objects that are related are not directly related from my model in question.

For example I have the following models (generically named to remain vague due to IP at my company):

  • ModelA which is the model I'm seeing the issue with when deleting from the Django Admin site
  • ModelB which contains a ForeignKey field to ModelA
  • ModelC which contains a ForeignKey field to ModelB
  • ModelD which contains a ForeignKey field to ModelC
  • ModelE which contains a ForeignKey field to ModelD

Model details:

  • ModelE can contain tens/hundreds/thousands of entries for any entry of
  • ModelC. Additionally ModelC can contain tens/hundreds/thousands of entries for any entry of ModelB

Currently when I try to delete ModelA Django attempts to generate all the associated objects all the way down to ModelE which is causing a timeout in certain cases with high number of associated ModelC and ModelE.

Is there a way to avoid this either by overriding a custom template such as delete_confirmation_template or through any other method? Ideally I would like to still show the summary, but I'm not sure that will be possible with the nature of this issue.

A few details for context:

  • I feel this may be due to a poor overall structure in our DB Schema, but like I mentioned earlier this is a Legacy system.
  • I do not need an immediate fix for this as I will actually never delete entries for this model except for my current scenario/task of cleaning up duplicated entries(user error not controlled correctly by forms; The forms now check for this) which is being done through a migration script. I simply noticed this when trying to clean up things and leverage this intermediate page as a sanity check when testing said migration script

Timeout screenshot

golkedj
  • 101
  • 6
  • Which version of Django? What's the `on_delete` value of the various `ForeignKey` fields? Are you implying that `on_delete` is set to `CASCADE` and therefore the admin is trying to show all the related models that will also be deleted? – dirkgroten Nov 20 '18 at 14:19
  • Django version 1.11 and yes in almost all cases it is set to CASCADE – golkedj Nov 20 '18 at 14:25
  • First, I would ask myself whether `CASCADE` is the correct behaviour (often with Django version < 2.x, developers just didn't think about the appropriate settings, so it defaulted to `CASCADE`). Maybe you want it to be `SET_NULL`, which would fix your issue. Second, if `CASCADE` is the correct behaviour, then there's not much you can do except changing the timeout settings: the fact that all the related models need to be fetched isn't just due to the displaying of the confirmation template, it will happen anyway when the actual `delete()` operation happens. – dirkgroten Nov 20 '18 at 14:31
  • @dirkgroten I have been thinking about that myself. With the nature of the data and the models I think it would be more appropriate for the on_delete to be `SET_NULL` in many cases. Specifically, for the `ModelC` and on, these should never be deleted as they are test results for an automated system and should always be preserved. Furthermore, `ModelA` should probably never be deleted either. I think for my current case I will simply disable the delete ability from the admin site (https://stackoverflow.com/questions/4043843/in-django-admin-how-do-i-disable-the-delete-link) – golkedj Nov 20 '18 at 14:38
  • you can set `has_delete_permission()` on your `ModelAdmin` class to return `False` (or check the user's role, e.g. return `True` only for `is_superuser`), see [here](https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_delete_permission) – dirkgroten Nov 20 '18 at 14:43
  • @dirkgroten Thank you for your comments. They were very helpful. I went with a modified version of your suggestion for using `SET_NULL`. In my case while `CASCADE` is not appropriate, `PROTECT` is. – golkedj Nov 20 '18 at 15:32

1 Answers1

1

From discussions in the comments I came to the following conclusion(s):

  • on_delete being set to CASCADE for models was incorrect and was causing the very high times in retrieving related objects when attempting to delete a model
  • Since I do not want to allow deleting of these objects when other specific models have associations to them I analyzed and appropriately set on_delete to PROTECT where applicable
  • Now when I attempt to delete an object it will not allow me to delete the object due to protected related items. It also resolves the timeout issue I was previously observing

This allows me to still delete objects from this model via the Django admin site IF they have no related protected objects, which in the end is the functionality I desire

golkedj
  • 101
  • 6