Хеширование пароля, если он не хешируется в django

Когда я пытаюсь создать пароль для пользователя с помощью интерфейса администратора, он не хэшируется. Поэтому я добавил эту строку в модель пользователя

    def save(self, *args, **kwargs):
        self.set_password(self.password)

Пока это решает проблему. При создании пользователя с помощью createsuperuser он сохраняет пароль в виде хэша, но когда я пытаюсь войти в интерфейс администратора, он говорит, что пароль неверный. Я уверен, что это вызвано добавлением вышеуказанной строки в код. Когда я удаляю строку, createsuperuser работает нормально, но пароль не хэшируется в интерфейсе администратора, когда я добавляю строку, admin работает, а createsuperuser - нет. Я хочу хэшировать пароль, если он еще не хэширован.

class CustomUser(AbstractUser):
    role = models.ForeignKey(to=Role, to_field='role', on_delete=models.CASCADE, null=True, blank=True)
    username = models.CharField(max_length=100, unique=True, editable=True, validators=[MinLengthValidator(5)], null=False)
    image = models.ImageField(upload_to='profile_pics/', blank=True)
    password = models.CharField(max_length=128)
    complaint = GenericRelation(Complaint)
    # Specify unique related names for the groups and user_permissions fields
    groups = models.ManyToManyField(
        Group,
        verbose_name=_('groups'),
        blank=True,
        help_text=_(
            'The groups this user belongs to. A user will get all permissions '
            'granted to each of their groups.'
        ),
        related_name='custom_users',  # Change the related name to 'custom_users'
    )

    user_permissions = models.ManyToManyField(
        Permission,
        verbose_name=_('user permissions'),
        blank=True,
        help_text=_('Specific permissions for this user.'),
        related_name='custom_users',  # Change the related name to 'custom_users'
    )

    def __str__(self):
        return f'{self.username}'

    def save(self, *args, **kwargs):
        if self.role_id == 'admin':
            self.is_staff = True

        if self.image:
            img = Image.open(self.image.path)

            if img.height > 300 or img.width > 300:
                output_size = (300, 300)
                img.thumbnail(output_size)
                img.save(self.image.path)
        super().save(*args, **kwargs)
@admin.register(CustomUser)
class CustomUserAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'image', 'role')

Не хэшируйте пароль в методе .save(…): он будет хэшировать пароль каждый раз, когда вы снова сохраняете объект модели. Поскольку метод createsuperuser уже хэширует пароль, он будет хэшировать пароль во второй раз, делая его бесполезным для (первого) пароля. Это потребует входа в систему с хэшем первого пароля.

В стандартной админке Django для User работает форма, которая хэширует его. Мы можем подключить ее и для пользовательской админки:

from django.contrib.auth.forms import UserChangeForm, UserCreationForm


class CustomUserCreationForm(UserCreationForm):
    class Meta:
        model = CustomUser
        fields = ('username', 'role', 'image')


class CustomUserChangeForm(UserChangeForm):
    class Meta:
        model = CustomUser
        fields = ('username', 'role', 'image')


@admin.register(CustomUser)
class CustomUserAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'image', 'role')
    form = CustomUserChangeForm
    add_form = CustomUserCreationForm

Это также обеспечит отображение пароля в виде <input type="password'>, скрывая его на экране.

Хеширование пароля в интерфейсе администратора.

from django.contrib.auth.hashers import make_password
class CustomUser(AbstractUser):
    ##
    def save(self, *args, **kwargs):
        # Check if the password is set and not already hashed
        if self.password and not self.password.startswith('pbkdf2_sha256$'):
            self.password = make_password(self.password)
        super().save(*args, **kwargs)
Вернуться на верх