تغيير اللغه الي العربية
Use Django's Authentication App part 2.
There is a small bug I saw in the django login view.
We need to tell him that his account is closed so he can contact the support to know the reason.
if we go to the source code of AuthenticationForm
The problem is if the user is inactive the authenticate() return None even if the username and password are correct so we have to override this function to check first if the user exists with only username and then check if its not active then return the confirm_login_allowed() instead of get_invalid_login_error()
You don't have to edit the confirm_login_allowed() but I just edited it to write more clear message rather than the default message (This account is inactive.)
Last Updated: 1 month, 1 week ago
Views: 428
Use Django's Authentication App part 2.
If you didn't read part 1 you should read it first here
There is a small bug I saw in the django login view.
let's assume that we have a user in our website that did some violation so we closed his account (i.e active = False).
when he login it won't alert him that the account is closed instead it will ask him to write correct username or password.
That's false information for the user, not very good user experience.

We need to tell him that his account is closed so he can contact the support to know the reason.
So let's fix that! inside our forms.py in users app we will create a custom login form, first we will edit our imports to add the Django AuthenticationForm and the authenticate function
#users/forms.py
from django import forms
from django.contrib.auth import authenticate, get_user_model
from django.contrib.auth.forms import (
AuthenticationForm,
UserChangeForm,
UserCreationForm,
)
User = get_user_model()
And then create our custom login form using the AuthenticationForm
if we go to the source code of AuthenticationForm
we will find a function called clean() and one called confirm_login_allowed()
class AuthenticationForm(forms.Form):
....
....
....
def clean(self):
username = self.cleaned_data.get("username")
password = self.cleaned_data.get("password")
if username is not None and password:
self.user_cache = authenticate(
self.request, username=username, password=password
)
if self.user_cache is None:
raise self.get_invalid_login_error()
else:
self.confirm_login_allowed(self.user_cache)
return self.cleaned_data
def confirm_login_allowed(self, user):
"""
Controls whether the given User may log in. This is a policy setting,
independent of end-user authentication. This default behavior is to
allow login by active users, and reject login by inactive users.
If the given user cannot log in, this method should raise a
``ValidationError``.
If the given user may log in, this method should return None.
"""
if not user.is_active:
raise ValidationError(
self.error_messages["inactive"],
code="inactive",
)
The problem is if the user is inactive the authenticate() return None even if the username and password are correct so we have to override this function to check first if the user exists with only username and then check if its not active then return the confirm_login_allowed() instead of get_invalid_login_error()
#users/forms.py
...
...
class CustomLoginForm(AuthenticationForm):
username = forms.CharField(
widget=forms.TextInput(attrs={"placeholder": "User Name"})
)
password = forms.CharField(
label="Password",
widget=forms.PasswordInput(attrs={"placeholder": "Password"}),
)
def clean(self):
username = self.cleaned_data.get("username")
password = self.cleaned_data.get("password")
if username is not None and password:
self.user_cache = authenticate(
self.request, username=username, password=password
)
if self.user_cache is None:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
user = None
if user is not None:
if not user.is_active:
self.confirm_login_allowed(user)
else:
raise self.get_invalid_login_error()
else:
raise self.get_invalid_login_error()
else:
self.confirm_login_allowed(self.user_cache)
return self.cleaned_data
def confirm_login_allowed(self, user):
if not user.is_active:
error = "The account is closed, please contact us for more details."
raise forms.ValidationError(error)
You don't have to edit the confirm_login_allowed() but I just edited it to write more clear message rather than the default message (This account is inactive.)
Now we need to add this form to our login view.
in urls.py file we add form_class to the view like this
# users/urls.py
from .forms import CustomLoginForm
urlpatterns = [
....
....
....
path("login/", django_views.LoginView.as_view(form_class=CustomLoginForm), name="login"),
]
Now you will see the message when you login with inactive user.

That's better right?
I hope the tutorial was simple.
Feel free to reach out if you have any questions.
Join to discord Server Here - Django Learn Together.
Views: 428