pythondjangodjango-custom-userdjango-managersdjango-shell

Django admin login only works with superusers created from shell


i have a custom user using AbstractUser just to add timestamps and a fk to it

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.conf import settings
from .managers import CustomUserManager

class SubUser(AbstractUser):
    if settings.DEBUG:
        parent_user_id = models.ForeignKey('self', on_delete=models.DO_NOTHING, null=True, blank=True)
    else:
        parent_user_id = models.ForeignKey('self', on_delete=models.RESTRICT, null=True, blank=True)

    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    USERNAME_FIELD = "username"

    objects = CustomUserManager()

    def __str__(self):
        return self.username

I read that to encrypt passwords well I must create a manager:

from django.contrib.auth.base_user import BaseUserManager

class CustomUserManager(BaseUserManager):
    def create_user(self, username, password=None, **extra_fields):
        user = self.model(username=username, **extra_fields)
        print(username)
        print(password)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, password=None, **extra_fields):
        user = self.create_user(username, password, **extra_fields)
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user

when i create a superuser from shell: u = SubUser.objects.create_superuser(username='asd', password='asdasd') the instance creates successfully, the password is encrypted and my login in admin/ with that superuser works but if i create a normal user: u = SubUser.objects.create_user(username='qwe', password='qweqwe') the instance creates successfully, the password is encrypted and BUT my login in admin/ DOESNT work

now, also i read that if I use a custom user i should use my manager, in the shell i did:

user_manager = CustomUserManager()
new_user = user_manager.create_user(username='qwe', password='qweqwe')

and get a error

user.save(using=self._db)
TypeError: 'NoneType' object is not callable

what did i do wrong? The users record well in the db, I looked directly at the db I use django 5.0.1 and sqlite3

when i create a superuser from shell: u = SubUser.objects.create_superuser(username='asd', password='asdasd') the instance creates successfully, the password is encrypted and my login in admin/ with that superuser works but if i create a normal user: u = SubUser.objects.create_user(username='qwe', password='qweqwe') the instance creates successfully, the password is encrypted and BUT my login in admin/ DOESNT work

now, also i read that if I use a custom user i should use my manager, in the shell i did:

user_manager = CustomUserManager()
new_user = user_manager.create_user(username='qwe', password='qweqwe')

and get a error

user.save(using=self._db)
TypeError: 'NoneType' object is not callable

what did i do wrong?, users should be created correctly but they are not The users record well in the db, I looked directly at the db I use django 5.0.1 and sqlite3


Solution

  • You should not work with the manager directly, this will not work. You use the manager with SubUser.objects, that way it will inject the model into the manager. Not by using the CustomUserManager(): if you construct such manager outside the model, it will not call .contribute_to_class() and thus inject the model into the manager.

    Furthermore it is normal behavior that a user that is not staff can not log in in the admin, since you need to be staff for this. You need to set .is_staff to True for that. So you can create a non-admin user with .is_staff set to True with:

    SubUser.objects.create_user(username='qwe', password='qweqwe', is_staff=True)