在AuthenticationForm中重写Clean方法后,authenticate返回None,并且不处理任何错误

时间:2018-06-06 20:06:55

标签: django django-forms django-views django-authentication

的朋友。

需要覆盖Сlean中的AuthenticationForm方法,以便在用户登录之前进一步检查是否存在属性。

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})

问题如下。当我尝试注册为数据库中的用户时,一切正常,但是当我输入一个不存在的登录时,我会抛弃:

AnonymousUser' object has no attribute '_meta'

指向login(request, user)。该错误是可以理解的,它无法登录不返回user = authenticate(username=username, password=password)的用户(它返回None)。

问题是它为什么不处理错误,必须有消息检查用户名或密码。

也许我没有正确地重新定义Clean中的AuthenticationForm方法?

UPD:

回溯:

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'

1 个答案:

答案 0 :(得分:0)

clean方法中,您只是在用户存在的情况下引发错误,但不是超级用户,也不是员工。

当用户根本不存在时,您也应该提出错误。

我会这样使用try,除了,否则。

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。我没有检查你的干净方法的逻辑除外   用户是否存在。

检查Django关于验证表单的文档。另外还有为什么你应该在被覆盖的clean()内调用超级。