friend.
There was a need to override the Сlean
method in AuthenticationForm
to further check for the presence of an attribute before the user can log in.
Forms.py:
from django.contrib.auth.forms import AuthenticationForm as BaseAuthenticationForm
from django.contrib.auth.models import User
from inc.models import Account, UserProfile, Counter
class AuthenticationForm(BaseAuthenticationForm):
def clean(self):
username = self.cleaned_data.get('username')
user = User.objects.filter(username = username).first()
if user != None:
print(user)
if not user.is_superuser and not user.is_staff:
account = Account.objects.filter(num_account = UserProfile.objects.filter(user__username = username).first().num_account).first()
have_counter = Counter.objects.filter(num_account = account).all()
if not have_counter:
raise forms.ValidationError('Some text...')
return self.cleaned_data
Views.py:
from django.contrib.auth import login, authenticate
from .forms import AuthenticationForm
def LogIn(request):
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
print(user)
login(request, user)
return redirect('/')
else:
print(form.errors)
else:
form = AuthenticationForm()
return render(request, 'userprocessing/login.html', {'form': form})
The problem is as follows. When I try to register as a user who is in the database everything works as it should, but when I enter a non-existent login I throw out:
AnonymousUser' object has no attribute '_meta'
which points to login(request, user)
. The error is understandable, it can not login the user which does not return user = authenticate(username=username, password=password)
(it returns None
).
The question is why it does not handle the error, there must be a message check the username or password.
Perhaps I did not correctly redefine Clean
method in AuthenticationForm
?
UPD:
Traceback:
Request Method: POST
Request URL: http://localhost:8000/login/?next=/
Django Version: 2.0.5
Python Version: 3.6.5
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'inc.apps.IncConfig',
'main.apps.MainConfig',
'django.contrib.admin']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "...\Python\Python36-32\lib\site-packages\django\core\handlers\exception.py" in inner
35. response = get_response(request)
File "...\Python\Python36-32\lib\site-packages\django\core\handlers\base.py" in _get_response
128. response = self.process_exception_by_middleware(e, request)
File "...\Python\Python36-32\lib\site-packages\django\core\handlers\base.py" in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "...\views.py" in LogIn
57. login(request, user)
File "...\Python\Python36-32\lib\site-packages\django\contrib\auth\__init__.py" in login
155. request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
File "...\Python\Python36-32\lib\site-packages\django\utils\functional.py" in inner
216. return func(self._wrapped, *args)
Exception Type: AttributeError at /login/
Exception Value: 'AnonymousUser' object has no attribute '_meta'
In your clean
method, you are only raising an error in a case the user exists but is not a superuser neither a staff.
You should also raise an error when the user does not exist at all.
I would do it this way using try, except, else.
def clean(self):
cleaned_data = super().clean()
username = cleaned_data.get('username')
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
raise forms.ValidationError('User does not exist...')
else:
print(user)
if not user.is_superuser and not user.is_staff:
account = Account.objects.filter(num_account=UserProfile.objects.filter(user__username=username).first().num_account).first()
have_counter = Counter.objects.filter(num_account=account).all()
if not have_counter:
raise forms.ValidationError('Some text...')
return cleaned_data
PS. I did not check the logic of your clean method except for whether the user exists or not.
Check Django's docs about validating forms. Also on why you should call super inside your overridden clean()
.