g3w-admin icon indicating copy to clipboard operation
g3w-admin copied to clipboard

Gracefully handle `ForeignKeyViolation` when permantely deleting special groups/projects

Open Raruto opened this issue 1 year ago • 1 comments

Checklist

  • [x] I've searched through the existing issues and this bug has never been reported before

Subject of the issue

I report here, although it is also related to the use of an external plugin (ie. innovapuglia).

Basically, there is no way to delete a group/project when it contains relationships with system tables: (e.g. qdjango_project):

image

I don't know if we can handle this in simple way, but at least let's try to show a more informative message than a generic 500 error (which is a bit scary, it almost feels like crashing)

Steps to reproduce

  1. install a plugin like innovapuglia
  2. upload a project related to that plugin
  3. uninstall the aforementioned plugin
  4. try to delete that group/project to get a 500 error

Environment

[g3wsdk.info]

  • g3w-admin: 3.7.delete_old_qgis_project_file-20231116140223
  • g3w-client: 3.9.0-alpha.2.0
  • browser: Firefox 119.0
  • operating system: Windows 11 64-bit

Link to your project

No response

Additional info

Docker logs:

[Errno 2] No such file or directory: '/shared-volume/media/projects/innovapuglia_iframeqgs.qgs'
[Errno 2] No such file or directory: '/shared-volume/media/projects/innovapuglia_iframeqgs.qgs'
ERROR:django.request:[Errno 2] No such file or directory: '/shared-volume/media/projects/innovapuglia_iframeqgs.qgs'
Internal Server Error: /en/admin/groups/delete/innovapuglia/
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 242, in _commit
    return self.connection.commit()
psycopg2.errors.ForeignKeyViolation: update or delete on table "qdjango_project" violates foreign key constraint "innovapuglia_ipproje_project_id_06580e92_fk_qdjango_p" on table "innovapuglia_ipprojects"
DETAIL:  Key (id)=(2) is still referenced from table "innovapuglia_ipprojects".
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.10/dist-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/guardian/decorators.py", line 124, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/code/g3w-admin/core/views.py", line 262, in dispatch
    return super(GroupDeleteView, self).dispatch(*args, **kwargs)
  File "/code/g3w-admin/core/mixins/views.py", line 22, in dispatch
    return super(G3WRequestViewMixin, self).dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/code/g3w-admin/core/views.py", line 266, in post
    res = super(GroupDeleteView, self).post(request, *args, **kwargs)
  File "/code/g3w-admin/core/mixins/views.py", line 102, in post
    self.object.delete();
  File "/usr/local/lib/python3.10/dist-packages/ordered_model/models.py", line 211, in delete
    super().delete(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/db/models/base.py", line 967, in delete
    return collector.delete()
  File "/usr/local/lib/python3.10/dist-packages/django/db/models/deletion.py", line 400, in delete
    with transaction.atomic(using=self.using, savepoint=False):
  File "/usr/local/lib/python3.10/dist-packages/django/db/transaction.py", line 246, in __exit__
    connection.commit()
  File "/usr/local/lib/python3.10/dist-packages/django/utils/asyncio.py", line 33, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 266, in commit
    self._commit()
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 241, in _commit
    with self.wrap_database_errors:
  File "/usr/local/lib/python3.10/dist-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 242, in _commit
    return self.connection.commit()
django.db.utils.IntegrityError: update or delete on table "qdjango_project" violates foreign key constraint "innovapuglia_ipproje_project_id_06580e92_fk_qdjango_p" on table "innovapuglia_ipprojects"
DETAIL:  Key (id)=(2) is still referenced from table "innovapuglia_ipprojects".
Internal Server Error: /en/admin/groups/delete/innovapuglia/
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 242, in _commit
    return self.connection.commit()
psycopg2.errors.ForeignKeyViolation: update or delete on table "qdjango_project" violates foreign key constraint "innovapuglia_ipproje_project_id_06580e92_fk_qdjango_p" on table "innovapuglia_ipprojects"
DETAIL:  Key (id)=(2) is still referenced from table "innovapuglia_ipprojects".
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.10/dist-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/guardian/decorators.py", line 124, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/code/g3w-admin/core/views.py", line 262, in dispatch
    return super(GroupDeleteView, self).dispatch(*args, **kwargs)
  File "/code/g3w-admin/core/mixins/views.py", line 22, in dispatch
    return super(G3WRequestViewMixin, self).dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/code/g3w-admin/core/views.py", line 266, in post
    res = super(GroupDeleteView, self).post(request, *args, **kwargs)
  File "/code/g3w-admin/core/mixins/views.py", line 102, in post
    self.object.delete();
  File "/usr/local/lib/python3.10/dist-packages/ordered_model/models.py", line 211, in delete
    super().delete(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/db/models/base.py", line 967, in delete
    return collector.delete()
  File "/usr/local/lib/python3.10/dist-packages/django/db/models/deletion.py", line 400, in delete
    with transaction.atomic(using=self.using, savepoint=False):
  File "/usr/local/lib/python3.10/dist-packages/django/db/transaction.py", line 246, in __exit__
    connection.commit()
  File "/usr/local/lib/python3.10/dist-packages/django/utils/asyncio.py", line 33, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 266, in commit
    self._commit()
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 241, in _commit
    with self.wrap_database_errors:
  File "/usr/local/lib/python3.10/dist-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 242, in _commit
    return self.connection.commit()
django.db.utils.IntegrityError: update or delete on table "qdjango_project" violates foreign key constraint "innovapuglia_ipproje_project_id_06580e92_fk_qdjango_p" on table "innovapuglia_ipprojects"
DETAIL:  Key (id)=(2) is still referenced from table "innovapuglia_ipprojects".
ERROR:django.request:Internal Server Error: /en/admin/groups/delete/innovapuglia/
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 242, in _commit
    return self.connection.commit()
psycopg2.errors.ForeignKeyViolation: update or delete on table "qdjango_project" violates foreign key constraint "innovapuglia_ipproje_project_id_06580e92_fk_qdjango_p" on table "innovapuglia_ipprojects"
DETAIL:  Key (id)=(2) is still referenced from table "innovapuglia_ipprojects".
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.10/dist-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/guardian/decorators.py", line 124, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/code/g3w-admin/core/views.py", line 262, in dispatch
    return super(GroupDeleteView, self).dispatch(*args, **kwargs)
  File "/code/g3w-admin/core/mixins/views.py", line 22, in dispatch
    return super(G3WRequestViewMixin, self).dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/code/g3w-admin/core/views.py", line 266, in post
    res = super(GroupDeleteView, self).post(request, *args, **kwargs)
  File "/code/g3w-admin/core/mixins/views.py", line 102, in post
    self.object.delete();
  File "/usr/local/lib/python3.10/dist-packages/ordered_model/models.py", line 211, in delete
    super().delete(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/db/models/base.py", line 967, in delete
    return collector.delete()
  File "/usr/local/lib/python3.10/dist-packages/django/db/models/deletion.py", line 400, in delete
    with transaction.atomic(using=self.using, savepoint=False):
  File "/usr/local/lib/python3.10/dist-packages/django/db/transaction.py", line 246, in __exit__
    connection.commit()
  File "/usr/local/lib/python3.10/dist-packages/django/utils/asyncio.py", line 33, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 266, in commit
    self._commit()
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 241, in _commit
    with self.wrap_database_errors:
  File "/usr/local/lib/python3.10/dist-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 242, in _commit
    return self.connection.commit()
django.db.utils.IntegrityError: update or delete on table "qdjango_project" violates foreign key constraint "innovapuglia_ipproje_project_id_06580e92_fk_qdjango_p" on table "innovapuglia_ipprojects"
DETAIL:  Key (id)=(2) is still referenced from table "innovapuglia_ipprojects".
[REQUEST] <741> "500 POST /en/admin/groups/delete/innovapuglia/ HTTP/1.1"

Raruto avatar Nov 16 '23 14:11 Raruto