Issue
So i create a custom model with AbstractUser:
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
phone = models.CharField(validators=[phone_regex], max_length=17, blank=False, null=False) # Validators should be a list
is_shop = models.BooleanField(default=False)
products = models.ManyToManyField('Product', blank=True)
class Meta:
db_table = "scrape_customuser"
def save(self, *args, **kwargs):
if not self.pk:
self.set_password(self.password)
super().save(*args, **kwargs)
and a sign up form
class UserForm(UserCreationForm):
class Meta:
model = CustomUser
fields = ['username', 'email', 'phone', 'password1', 'password2']
my login logic:
def shop_user_signup(request):
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.is_shop = True
user.save()
login(request, user)
referring_url = request.POST.get('next', None)
if referring_url:
return redirect(referring_url)
else:
return redirect('/')
else:
form = UserForm()
return render(request, 'shop_user_signup.html', {'form': form})
The user got created in the database with password got hash to something like this pbkdf2_sha256$600000$TvRyCcSY6eMhnV1i1urh93$aKLqPBrcma5KsuS469crJtS93UI0h+7pduJXeW6ukAU=
, is_active=1
and somehow the last login is 2023-11-23 15:49:22.581983
even though the redirect didn't show username when i have
<li class="nav-item">
{% if user.is_authenticated %}
<a class="nav-link" href="{% url 'logout' %}">{{user.username}} | Logout</a>
{% else %}
<a class="nav-link" href="{% url 'login' %}">Login</a>
{% endif %}
</li>
When i try to login in the login page i got the error Please enter a correct username and password. Note that both fields may be case-sensitive.
And the admin account can login normally.
Solution
Don't set the password in the model. This will hash the password a second time: once by the form, and once by the model. Indeed, if we look at the BaseUserCreationForm
, we see [GitHub]:
def save(self, commit=True): user = super().save(commit=False) user.set_password(self.cleaned_data["password1"]) if commit: user.save() if hasattr(self, "save_m2m"): self.save_m2m() return user
So omit rehashing it a second time:
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
phone_regex = RegexValidator(
regex=r'^\+?1?\d{9,15}$',
message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.",
)
phone = models.CharField(
validators=[phone_regex], max_length=17, blank=False, null=False
) # Validators should be a list
is_shop = models.BooleanField(default=False)
products = models.ManyToManyField('Product', blank=True)
class Meta:
db_table = 'scrape_customuser'
# no override
You can simplify the view to:
def shop_user_signup(request):
if request.method == 'POST':
form = UserForm(request.POST, request.FILES)
if form.is_valid():
form.instance.is_shop = True
user = form.save()
login(request, user)
referring_url = request.POST.get('next', None)
if referring_url:
return redirect(referring_url)
else:
return redirect('/')
else:
form = UserForm()
return render(request, 'shop_user_signup.html', {'form': form})
and in the template, check:
{% if request.user.is_authenticated %}
<!-- … -->
{% endif %}
Answered By - willeM_ Van Onsem
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.