I am using a custom user for Django authentication and I keep getting the error in the title every time I try to create a super user. The more confusing thing is, the user seems to be registered because when I try to use the email in the next creation, it says that the email has been used but then when I try to login, it says that the user has no profile.
The user model has the following code:
from typing import ClassVar
from django.utils import timezone
from django.contrib.auth.models import AbstractBaseUser,PermissionsMixin, Group, Permission
from django.db import models
from django.db.models import BooleanField
from django.db.models import CharField
from django.db.models import EmailField
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from rhs_soccer.users.enums import UserRoles
from .managers import UserManager
class User(AbstractBaseUser, PermissionsMixin):
"""
Default custom user model for RHS Boys Soccer Club.
If adding fields that need to be filled at user signup,
check forms.SignupForm and forms.SocialSignupForms accordingly.
"""
# First and last name do not cover name patterns around the globe
#id = models.UUIDField(default=uuid.uuid4, primary_key = True, editable=False, unique=True)
first_name = CharField(_("first name"), max_length=30, blank = True, null = True)
last_name = CharField(_("last name"), max_length=30, blank = True, null = True)
email = EmailField(_("email address"), unique=True)
role = CharField(
_("Role"),
max_length=50,
choices=UserRoles.choices(),
default=UserRoles.PLAYER.value,
)
username = None # type: ignore[assignment]
is_active = BooleanField(_("active"), default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
groups = models.ManyToManyField(
Group,
related_name="user_set",
related_query_name="user",
blank=True,
)
user_permissions = models.ManyToManyField(
Permission,
related_name="user_set",
related_query_name="user",
blank=True,
)
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
objects: ClassVar[UserManager] = UserManager()
def get_absolute_url(self) -> str:
"""Get URL for user's detail view.
Returns:
str: URL for user detail.
"""
return reverse("users:detail", kwargs={"pk": self.id})
def __str__(self) -> str:
return self.email
def get_full_name(self) -> str:
return f"{self.first_name} {self.last_name}"
The user managers.py file has the following code:
from typing import TYPE_CHECKING
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import BaseUserManager
from django.utils import timezone
# from django.contrib.auth.models import UserManager as DjangoUserManager
if TYPE_CHECKING:
from .models import User # noqa: F401
class UserManager(BaseUserManager):
"""Custom manager for the User model."""
def _create_user(self, email: str, password: str | None, **extra_fields):
"""
Create and save a user with the given email and password.
"""
if not email:
msg = "The given email must be set"
raise ValueError(msg)
email = self.normalize_email(email)
extra_fields.setdefault('date_joined', timezone.now())
user = self.model(email=email, **extra_fields)
user.password = make_password(password)
user.save(using=self._db)
return user
def create_user(self, email: str, password: str | None = None, **extra_fields): # type: ignore[override]
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", False)
return self._create_user(email, password, **extra_fields)
def create_player(self, email: str, password: str | None = None, **extra_fields): # type: ignore[override]
extra_fields.setdefault("is_staff", False)
extra_fields.setdefault("is_superuser", False)
extra_fields.setdefault("role", "PLAYER")
return self._create_user(email, password, **extra_fields)
def create_coach(self, email: str, password: str | None = None, **extra_fields): # type: ignore[override]
extra_fields.setdefault("is_staff", False)
extra_fields.setdefault("is_superuser", False)
extra_fields.setdefault("role", "COACH")
return self._create_user(email, password, **extra_fields)
def create_manager(self, email: str, password: str | None = None, **extra_fields): # type: ignore[override]
extra_fields.setdefault("is_staff", False)
extra_fields.setdefault("is_superuser", False)
extra_fields.setdefault("role", "MANAGER")
return self._create_user(email, password, **extra_fields)
def create_parent(self, email: str, password: str | None = None, **extra_fields): # type: ignore[override]
extra_fields.setdefault("is_staff", False)
extra_fields.setdefault("is_superuser", False)
extra_fields.setdefault("role", "PARENT")
return self._create_user(email, password, **extra_fields)
def create_admin(self, email: str, password: str | None = None, **extra_fields): # type: ignore[override]
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("role", "ADMIN")
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email: str, password: str | None = None, **extra_fields): # type: ignore[override]
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("role", "ADMIN")
if 'first_name' not in extra_fields:
extra_fields['first_name'] = ''
if 'last_name' not in extra_fields:
extra_fields['last_name'] = ''
if extra_fields.get("is_staff") is not True:
msg = "Superuser must have is_staff=True."
raise ValueError(msg)
if extra_fields.get("is_superuser") is not True:
msg = "Superuser must have is_superuser=True."
raise ValueError(msg)
return self._create_user(email, password, **extra_fields)
The forms.py has the following code:
from allauth.account.forms import SignupForm
from allauth.socialaccount.forms import SignupForm as SocialSignupForm
from django.contrib.auth import forms as admin_forms
from django.forms import EmailField
from django.utils.translation import gettext_lazy as _
from django import forms
from .models import User
class UserAdminChangeForm(admin_forms.UserChangeForm):
class Meta(admin_forms.UserChangeForm.Meta): # type: ignore[name-defined]
model = User
fields = ('email', 'first_name', 'last_name', 'role', 'is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')
field_classes = {"email": EmailField}
class UserAdminCreationForm(admin_forms.UserCreationForm):
"""
Form for User Creation in the Admin Area.
To change user signup, see UserSignupForm and UserSocialSignupForm.
"""
first_name = forms.CharField(required=False)
last_name = forms.CharField(required=False)
class Meta(admin_forms.UserCreationForm.Meta): # type: ignore[name-defined]
model = User
fields = ("email","first_name", "last_name", "role", "password1", "password2")
field_classes = {"email": EmailField}
error_messages = {
"email": {"unique": _("This email has already been taken.")},
}
class UserSignupForm(SignupForm):
"""
Form that will be rendered on a user sign up section/screen.
Default fields will be added automatically.
Check UserSocialSignupForm for accounts created from social.
"""
class UserSocialSignupForm(SocialSignupForm):
"""
Renders the form when user has signed up using social accounts.
Default fields will be added automatically.
See UserSignupForm otherwise.
"""
The admin.py file has the following code:
from allauth.account.decorators import secure_admin_login
from django.conf import settings
from django.contrib import admin
#from django.contrib.auth import admin as auth_admin
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .forms import UserAdminChangeForm
from .forms import UserAdminCreationForm
from .models import User
if settings.DJANGO_ADMIN_FORCE_ALLAUTH:
# Force the `admin` sign in process to go through the `django-allauth` workflow:
# https://docs.allauth.org/en/latest/common/admin.html#admin
admin.autodiscover()
admin.site.login = secure_admin_login(admin.site.login) # type: ignore[method-assign]
@admin.register(User)
class UserAdmin(BaseUserAdmin):
form = UserAdminChangeForm
add_form = UserAdminCreationForm
fieldsets = (
(None, {"fields": ("email", "role", "password")}),
(
_("Personal info"),
{
"fields": (
"first_name",
"last_name",
),
},
),
(
_("Permissions"),
{
"fields": (
"is_active",
"is_staff",
"is_superuser",
"groups",
"user_permissions",
),
},
),
(_("Important dates"), {"fields": ("last_login", "date_joined")}),
)
list_display = ["email", "first_name", "last_name", "role"]
search_fields = [
"first_name",
"last_name",
"email"
]
list_editable = ["role"]
list_filter = ["role"]
ordering = ["id"]
add_fieldsets = (
(
None,
{
"classes": ("wide",),
"fields": ("email", "role", "password1", "password2", "first_name", "last_name"),
},
),
)
when I run the python manage.py createsuperuser, I only get the fields to fill in the email, password1 and to verify the password, but I then get the error CommandError: This field cannot be blank.; This field cannot be null.; This field cannot be blank.; This field cannot be blank. I do not even know which field the error is reffering to. Any leads?
Except for the unknown part
of your source code, there was no problem when I tested it with the same code.
models.py
class User(AbstractBaseUser, PermissionsMixin):
PLAYER = 'PR'
COACH = 'CO'
MANAGER = 'MG'
PARENT = 'PR'
ADMIN = 'AM'
ROLES = [
(PLAYER, 'PLAYER'),
(COACH, 'COACH'),
(MANAGER, 'MANAGER'),
(PARENT, 'PARENT'),
(ADMIN, 'ADMIN')
]
...
role = CharField(
_("Role"),
max_length=50,
choices=ROLES,
default=PLAYER,
)
...
forms.py
admin.autodiscover()
admin.site.login = secure_admin_login(admin.site.login) # type: ignore[method-assign]
The actual call of the troubled createsuperuser command corresponds to the handle method in this file.
The error message to the questioner seems to be related to the user model's REQUIRED_FIELDS value, but the questioner's REQUIRED_FIELDS is empty.
That's why I don't understand why the questioner's error occurs.
However, I would like you to try debugging this part of the problem.
for field_name in self.UserModel.REQUIRED_FIELDS:
field = self.UserModel._meta.get_field(field_name)
user_data[field_name] = options[field_name]
if user_data[field_name] is not None:
user_data[field_name] = field.clean(user_data[field_name], None)
while user_data[field_name] is None:
message = self._get_input_message(field)
input_value = self.get_input_data(field, message)
user_data[field_name] = input_value
if field.many_to_many and input_value:
if not input_value.strip():
user_data[field_name] = None
self.stderr.write("Error: This field cannot be blank.")
continue
user_data[field_name] = [pk.strip() for pk in input_value.split(",")]
if not field.many_to_many:
fake_user_data[field_name] = user_data[field_name]
# Wrap any foreign keys in fake model instances.
if field.many_to_one:
fake_user_data[field_name] = field.remote_field.model(user_data[field_name])
There seems to be a problem in this area. I would like to try debugging more, but no error occurred in my code. If debugging this part does not solve the problem, please attach the contents settings.py to question body.