summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/auth/models.py10
-rw-r--r--tests/auth_tests/test_models.py37
2 files changed, 43 insertions, 4 deletions
diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
index 84962b9d0e..5f092f0ae8 100644
--- a/django/contrib/auth/models.py
+++ b/django/contrib/auth/models.py
@@ -1,5 +1,7 @@
+from django.apps import apps
from django.contrib import auth
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
+from django.contrib.auth.hashers import make_password
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.core.mail import send_mail
@@ -134,9 +136,13 @@ class UserManager(BaseUserManager):
if not username:
raise ValueError('The given username must be set')
email = self.normalize_email(email)
- username = self.model.normalize_username(username)
+ # Lookup the real model class from the global app registry so this
+ # manager method can be used in migrations. This is fine because
+ # managers are by definition working on the real model.
+ GlobalUserModel = apps.get_model(self.model._meta.app_label, self.model._meta.object_name)
+ username = GlobalUserModel.normalize_username(username)
user = self.model(username=username, email=email, **extra_fields)
- user.set_password(password)
+ user.password = make_password(password)
user.save(using=self._db)
return user
diff --git a/tests/auth_tests/test_models.py b/tests/auth_tests/test_models.py
index c60b66c993..2379f68b83 100644
--- a/tests/auth_tests/test_models.py
+++ b/tests/auth_tests/test_models.py
@@ -10,8 +10,12 @@ from django.contrib.auth.models import (
)
from django.contrib.contenttypes.models import ContentType
from django.core import mail
+from django.db import connection, migrations
+from django.db.migrations.state import ModelState, ProjectState
from django.db.models.signals import post_save
-from django.test import SimpleTestCase, TestCase, override_settings
+from django.test import (
+ SimpleTestCase, TestCase, TransactionTestCase, override_settings,
+)
from .models import IntegerUsernameUser
from .models.with_custom_email_field import CustomEmailField
@@ -101,7 +105,12 @@ class LoadDataWithNaturalKeysAndMultipleDatabasesTestCase(TestCase):
self.assertEqual(perm_other.content_type_id, other_objects[0].id)
-class UserManagerTestCase(TestCase):
+class UserManagerTestCase(TransactionTestCase):
+ available_apps = [
+ 'auth_tests',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ ]
def test_create_user(self):
email_lowercase = 'normal@normal.com'
@@ -156,6 +165,30 @@ class UserManagerTestCase(TestCase):
for char in password:
self.assertIn(char, allowed_chars)
+ def test_runpython_manager_methods(self):
+ def forwards(apps, schema_editor):
+ UserModel = apps.get_model('auth', 'User')
+ user = UserModel.objects.create_user('user1', password='secure')
+ self.assertIsInstance(user, UserModel)
+
+ operation = migrations.RunPython(forwards, migrations.RunPython.noop)
+ project_state = ProjectState()
+ project_state.add_model(ModelState.from_model(User))
+ project_state.add_model(ModelState.from_model(Group))
+ project_state.add_model(ModelState.from_model(Permission))
+ project_state.add_model(ModelState.from_model(ContentType))
+ new_state = project_state.clone()
+ with connection.schema_editor() as editor:
+ operation.state_forwards('test_manager_methods', new_state)
+ operation.database_forwards(
+ 'test_manager_methods',
+ editor,
+ project_state,
+ new_state,
+ )
+ user = User.objects.get(username='user1')
+ self.assertTrue(user.check_password('secure'))
+
class AbstractBaseUserTests(SimpleTestCase):