Przeglądaj źródła

Fixed #29132 -- Avoided connecting update_last_login() handler if User.last_login isn't a field.

Mikhail Porokhovnichenko 7 lat temu
rodzic
commit
14e34dcf8c

+ 4 - 1
django/contrib/auth/apps.py

@@ -1,5 +1,6 @@
 from django.apps import AppConfig
 from django.core import checks
+from django.db.models.query_utils import DeferredAttribute
 from django.db.models.signals import post_migrate
 from django.utils.translation import gettext_lazy as _
 
@@ -18,7 +19,9 @@ class AuthConfig(AppConfig):
             create_permissions,
             dispatch_uid="django.contrib.auth.management.create_permissions"
         )
-        if hasattr(get_user_model(), 'last_login'):
+        last_login_field = getattr(get_user_model(), 'last_login', None)
+        # Register the handler only if UserModel.last_login is a field.
+        if isinstance(last_login_field, DeferredAttribute):
             from .models import update_last_login
             user_logged_in.connect(update_last_login, dispatch_uid='update_last_login')
         checks.register(check_user_model, checks.Tags.models)

+ 2 - 1
tests/auth_tests/models/__init__.py

@@ -8,10 +8,11 @@ from .minimal import MinimalUser
 from .uuid_pk import UUIDUser
 from .with_foreign_key import CustomUserWithFK, Email
 from .with_integer_username import IntegerUsernameUser
+from .with_last_login_attr import UserWithDisabledLastLoginField
 
 __all__ = (
     'CustomUser', 'CustomUserWithoutIsActiveField', 'CustomPermissionsUser',
     'CustomUserWithFK', 'Email', 'ExtensionUser', 'IsActiveTestUser1',
     'MinimalUser', 'UUIDUser', 'CustomUserNonUniqueUsername',
-    'IntegerUsernameUser',
+    'IntegerUsernameUser', 'UserWithDisabledLastLoginField',
 )

+ 5 - 0
tests/auth_tests/models/with_last_login_attr.py

@@ -0,0 +1,5 @@
+from django.contrib.auth.base_user import AbstractBaseUser
+
+
+class UserWithDisabledLastLoginField(AbstractBaseUser):
+    last_login = None

+ 7 - 1
tests/auth_tests/test_signals.py

@@ -5,7 +5,7 @@ from django.core.exceptions import FieldDoesNotExist
 from django.test import TestCase, override_settings
 from django.test.client import RequestFactory
 
-from .models import MinimalUser
+from .models import MinimalUser, UserWithDisabledLastLoginField
 
 
 @override_settings(ROOT_URLCONF='auth_tests.urls')
@@ -101,6 +101,12 @@ class SignalTestCase(TestCase):
                 apps.get_app_config('auth').ready()
             self.assertEqual(signals.user_logged_in.receivers, [])
 
+            # last_login is a property whose value is None.
+            self.assertIsNone(UserWithDisabledLastLoginField().last_login)
+            with self.settings(AUTH_USER_MODEL='auth_tests.UserWithDisabledLastLoginField'):
+                apps.get_app_config('auth').ready()
+            self.assertEqual(signals.user_logged_in.receivers, [])
+
             with self.settings(AUTH_USER_MODEL='auth.User'):
                 apps.get_app_config('auth').ready()
             self.assertEqual(len(signals.user_logged_in.receivers), 1)