Repository: django-hijack/django-hijack

Issue:
Custom managers may cause issues during table locking
      I ran into the same issue, the underlying reason was a `select_related` call to an optional ForeignKey via a reverse_relation in my managers `get_queryset` method. However, I have several managers on my model and `objects` is not the same as the [default manager](https://docs.djangoproject.com/en/4.1/topics/db/managers/#django.db.models.Model._default_manager).

Changing
```next(get_user_model().objects.select_for_update().iterator()) ```
to
```next(get_user_model()._default_manager.select_for_update().iterator()) ```
would be enough to solve the problem for me. 

Additionally, the current version does not work for anyone who [changed their manager's name](https://docs.djangoproject.com/en/4.1/topics/db/managers/#manager-names).

Money Quote from [the docs](https://docs.djangoproject.com/en/4.1/topics/db/managers/#default-managers):

> If you’re writing some code that must handle an unknown model, for example, in a third-party app that implements a generic view, use this manager (or [_base_manager](https://docs.djangoproject.com/en/4.1/topics/db/managers/#django.db.models.Model._base_manager)) rather than assuming the model has an objects manager.

_Originally posted by @simonkern in https://github.com/django-hijack/django-hijack/discussions/411#discussioncomment-4490342_
    


Discussion:

Resolving patch:
diff --git a/hijack/views.py b/hijack/views.py
--- a/hijack/views.py
+++ b/hijack/views.py
@@ -64,7 +64,7 @@ class LockUserTableMixin:
     @transaction.atomic()
     def dispatch(self, request, *args, **kwargs):
         # Lock entire user table to avoid race conditions
-        next(get_user_model().objects.select_for_update().iterator())
+        next(get_user_model()._base_manager.select_for_update().iterator())
         return super().dispatch(request, *args, **kwargs)
 
 


Test patch:
diff --git a/hijack/tests/test_app/models.py b/hijack/tests/test_app/models.py
--- a/hijack/tests/test_app/models.py
+++ b/hijack/tests/test_app/models.py
@@ -1,13 +1,20 @@
 import uuid
 
 from django.conf import settings
-from django.contrib.auth.models import AbstractUser
+from django.contrib.auth.models import AbstractUser, UserManager
 from django.db import models
 
 
+class CustomUserManager(UserManager):
+    def select_for_update(self):
+        raise NotImplementedError
+
+
 class CustomUser(AbstractUser):
     uuid = models.UUIDField(editable=False, default=uuid.uuid4, primary_key=True)
 
+    objects = CustomUserManager()
+
 
 class Post(models.Model):
     author = models.ForeignKey(
diff --git a/hijack/tests/test_views.py b/hijack/tests/test_views.py
--- a/hijack/tests/test_views.py
+++ b/hijack/tests/test_views.py
@@ -7,10 +7,20 @@
 from django.contrib.sessions.models import Session
 from django.urls import reverse_lazy
 from django.utils import timezone
+from django.views import View
 
 from hijack import views
 
 
+class TestLockUserTableMixin:
+    @pytest.mark.django_db(transaction=True)
+    def test_dispatch__custom_manager(self, admin_user, rf):
+        class LockedView(views.LockUserTableMixin, View):
+            pass
+
+        LockedView().dispatch(rf.get("/"))
+
+
 class TestSuccessUrlMixin:
     def test_get_success_url__path(self):
         view = views.SuccessUrlMixin()