pythondjangodjango-modelsstring-hashing

How can i use 'set_password' in custom non-admin model?


I want to use hashing field set_password from User model in django.contrib.auth.models and I'm currently using a custom User model for that.

I'm getting the following error: Attribute error: 'User' object has no attribute 'set_password'

models.py

from django.db import models


class User(models.Model):
    first_name = models.CharField(max_length=50, blank=True)
    last_name = models.CharField(max_length=50, blank=True)
    profile_picture = 
     models.ImageField(upload_to="user_data/profile_picture", blank=True)
    username = models.CharField(max_length=100)
    birth_date = models.DateField(blank=True)
    gender = models.CharField(max_length=10, blank=True)
    password = models.CharField(max_length=1000)
    contact = models.CharField(max_length=10, blank=True)
    email = models.CharField(max_length=100)
    time_stamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.username

views.py

...
from .models import User

...
    def post(self, request):
        # Data is here
        form = self.form_class(request.POST)
        if form.is_valid():
            # create object of form
            user = form.save(commit=False)

            # cleaned/normalised data
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']

            # convert plain password into hashed
            user.set_password(user.password)
            user.save()

            return HttpResponse('Done here.')
            ...

forms.py (just used a widget in forms.py)

from .models import User
from django import forms


class UserForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ['username', 'password']

Solution

  • This is a really easy fix. Just change your models.py file like so:

    from django.contrib.auth.models import AbstractBaseUser
    
    class User(AbstractBaseUser):
        first_name = models.CharField(max_length=50, blank=True)
        last_name = models.CharField(max_length=50, blank=True)
        profile_picture = models.ImageField(upload_to="user_data/profile_picture", blank=True)
        username = models.CharField(max_length=100)
        birth_date = models.DateField(blank=True)
        gender = models.CharField(max_length=10, blank=True)
        password = models.CharField(max_length=1000)
        contact = models.CharField(max_length=10, blank=True)
        email = models.CharField(max_length=100)
        time_stamp = models.DateTimeField(auto_now_add=True)
    
        def __str__(self):
            return self.username
    

    That way, your user model will inherit all of the AbstractBaseUser methods, including set_password.

    Look at this full example from the documentation for extra information.