Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions pytest_django/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,33 +262,41 @@ def django_username_field(django_user_model):
@pytest.fixture()
def admin_user(db, django_user_model, django_username_field):
"""A Django admin user.

This uses an existing user with username "admin", or creates a new one with
password "password".
"""
UserModel = django_user_model
username_field = django_username_field
username = "admin@example.com" if username_field == "email" else "admin"
attributes = {username_field: username}

try:
user = UserModel._default_manager.get(**{username_field: username})
user = UserModel._default_manager.get(**attributes)
except UserModel.DoesNotExist:
extra_fields = {}
if username_field not in ("username", "email"):
extra_fields[username_field] = "admin"
all_user_model_fields = [x.name for x in UserModel._meta.get_fields()]

if 'username' in all_user_model_fields:
# django.contrib.auth.UserManager expects a username field to be
# present, even if a different USERNAME_FIELD is set.
attributes['username'] = 'admin'
if 'email' in all_user_model_fields:
# Handle both email field required for default UserManager and
# cases where USERNAME_FIELD is the email.
attributes['email'] = 'admin@example.com'

user = UserModel._default_manager.create_superuser(
username, "admin@example.com", "password", **extra_fields
password='password', **attributes
)
return user


@pytest.fixture()
def admin_client(db, admin_user):
def admin_client(db, admin_user, django_username_field):
"""A Django test client logged in as an admin user."""
from django.test.client import Client

client = Client()
client.login(username=admin_user.username, password="password")
client.login(username=getattr(admin_user, django_username_field), password='password')
return client


Expand Down
90 changes: 76 additions & 14 deletions tests/test_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ def test_with_live_server(live_server):


@pytest.mark.parametrize("username_field", ("email", "identifier"))
@pytest.mark.parametrize("original_username_field_present", (True, False))
@pytest.mark.django_project(
extra_settings="""
AUTH_USER_MODEL = 'app.MyCustomUser'
Expand All @@ -487,20 +488,76 @@ def test_with_live_server(live_server):
ROOT_URLCONF = 'tpkg.app.urls'
"""
)
def test_custom_user_model(django_testdir, username_field):
django_testdir.create_app_file(
"""
from django.contrib.auth.models import AbstractUser
from django.db import models
def test_custom_user_model(django_testdir, username_field, original_username_field_present):
if original_username_field_present:
django_testdir.create_app_file(
"""
from django.contrib.auth.models import AbstractUser
from django.db import models

class MyCustomUser(AbstractUser):
identifier = models.CharField(unique=True, max_length=100)
class MyCustomUser(AbstractUser):
identifier = models.CharField(unique=True, max_length=100)

USERNAME_FIELD = '%s'
"""
% (username_field),
"models.py",
)
USERNAME_FIELD = '%s'
"""
% (username_field),
"models.py",
)
else:
django_testdir.create_app_file(
"""
from django.contrib.auth.models import BaseUserManager

class MyCustomUserManager(BaseUserManager):
def _create_user(self, email, password, **extra_fields):
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user

def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)

def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)

if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')

return self._create_user(email, password, **extra_fields)
""",
"managers.py"
)
django_testdir.create_app_file(
"""
from django.contrib.auth.models import AbstractUser
from django.db import models

from .managers import MyCustomUserManager

class MyCustomUser(AbstractUser):
identifier = models.CharField(unique=True, max_length=100)

USERNAME_FIELD = '%s'
REQUIRED_FIELDS = []
objects = MyCustomUserManager()

username_field = MyCustomUser._meta.get_field('username')
local_fields = MyCustomUser._meta.local_fields
local_fields.remove(username_field)
MyCustomUser._meta.fields = local_fields
"""
% (username_field),
"models.py",
)
django_testdir.create_app_file(
"""
from django.conf.urls import url
Expand Down Expand Up @@ -539,6 +596,10 @@ def test_custom_user_model(admin_client):
)

django_testdir.create_app_file("", "migrations/__init__.py")
username_db_field = ""
if original_username_field_present:
username_db_field = "('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, max_length=30, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.', 'invalid')], help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, verbose_name='username'))," # noqa: E501

django_testdir.create_app_file(
"""
# -*- coding: utf-8 -*-
Expand All @@ -564,7 +625,7 @@ class Migration(migrations.Migration):
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(null=True, verbose_name='last login', blank=True)),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, max_length=30, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.', 'invalid')], help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, verbose_name='username')),
%s
('first_name', models.CharField(max_length=30, verbose_name='first name', blank=True)),
('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)),
('email', models.EmailField(max_length=254, verbose_name='email address', blank=True)),
Expand All @@ -583,7 +644,8 @@ class Migration(migrations.Migration):
bases=None,
),
]
""", # noqa: E501
""" # noqa: E501
% (username_db_field),
"migrations/0002_custom_user_model.py",
)

Expand Down