django - Django 自定义登录表单不会针对 is_valid() 进行验证
问题描述
摘要: 我的自定义登录表单无法针对 .is_valid() 进行验证。我已经能够确认电子邮件和密码值正在传递给views.py,因为print(request.POST.get('')返回电子邮件(登录所需)和密码。
我认为我的问题与其他类似问题不同,因为它们似乎都解决了缺少的必填字段。我尝试从 .is_valid 中排除我能想到的每个字段,但表单无法验证。
我单击按钮,没有任何反应(数据移动,这很奇怪,因为表单仍然无法验证 validate 并且我的登录不起作用 - 请参阅底部的日志)。我正在使用 Django 3.7。
帐户/forms.py
class LoginForm(forms.Form):
email = forms.EmailField(label='email', max_length='255')
password = forms.CharField(label='password')
def __init__(self, request, *args, **kwargs):
self.request = request
super(LoginForm, self).__init__(*args, **kwargs)
def form_valid(self, form):
form.save()
return super(LoginForm, self).form_valid(form)
accounts/views.py 我无法访问“form.is_valid”if 语句中的任何内容。我在相应的 else 语句处退出(如下所述)。
def login_page(request):
if request.method == 'POST': #create form instance / populate
form = LoginForm(request.POST)
context = {
"email": "email",
"password": "password",
"first_name": "first_name",
"last_name": "last_name",
"is_active": "is_active",
"form": form
}
if form.is_valid():
username = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
user = authenticate(request, username=username, password=password)
form.save()
if user is not None:
if user.is_active:
login(request, user)
print(request.is_authenticated())
context['form'] = LoginForm()
return redirect('/')
else:
pass
else:
pass
else:
'''This is where I always end up in the code'''
print("Error with if form.is_valid():")
return render(request, "account/login.html", context)
else:
return render(request, "account/login.html")
帐户/urls.py
app_name = 'accounts'
from .views import login_page
urlpatterns = [
path('login/', login_page, name="login")
]
登录.html
{% extends '_base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block title %}Login{% endblock title %}
{% block content %}
<h1>Login</h1>
<form method="post" class="form" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-success" type="submit">Log In</button>
</form>
{% endblock content %}
settings.py 我拥有 django 推荐用于身份验证和后端的所有必需应用程序。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
# Third-party
'crispy_forms',
# Local
'accounts.apps.AccountsConfig'
]
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',
]
AUTH_USER_MODEL = 'accounts.User'
LOGIN_REDIRECT_URL = 'carts:cart_update'
ACCOUNT_FORMS = {'login': 'accounts.forms.LoginForm'}
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'allauth.account.auth_backends.AuthenticationBackend',
)
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
ACCOUNT_SESSION_REMEMBER = True
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 4
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 300
accounts/model.py - 自定义用户模型 我正在使用的教程使用自定义用户文件,但我不确定这是否是问题的一部分。我怀疑它不相关,但我将其包括在内以防万一。
DEFAULT_ACTIVATION_DAYS = getattr(settings, 'DEFAULT_ACTIVATION_DAYS', 7)
class UserManager(BaseUserManager):
def create_user(self, email, first_name=None, last_name=None,
password=None, is_active=True, is_staff=False, is_admin=False):
if not email:
raise ValueError("Users must have an email address")
if not password:
raise ValueError("Users must have a password")
user_obj = self.model(
email=self.normalize_email(email),
)
user_obj.set_password(password) # change user password
user_obj.staff = is_staff
user_obj.admin = is_admin
user_obj.is_active = is_active
user_obj.save(using=self._db)
return user_obj
def create_staffuser(self, email,first_name=None, last_name=None,
password=None):
user = self.create_user(
email,
first_name=first_name,
last_name=last_name,
password=password,
is_staff=True
)
return user
def create_superuser(self, email, first_name=None,last_name=None, password=None):
user = self.create_user(
email,
first_name=first_name,
last_name=last_name,
password=password,
is_staff=True,
is_admin=True
)
return user
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
first_name = models.CharField(max_length=255, blank=True, null=True)
last_name = models.CharField(max_length=255, blank=True, null=True)
is_active = models.BooleanField(default=True, blank=True, null=True) # can login
staff = models.BooleanField(default=False, blank=True, null=True) # staff user non superuser
admin = models.BooleanField(default=False, blank=True, null=True) # superuser
timestamp = models.DateTimeField(auto_now_add=True, blank=True, null=True)
USERNAME_FIELD = 'email' #username
# USERNAME_FIELD and password are required by default
REQUIRED_FIELDS = [] #['full_name'] #python manage.py createsuperuser
objects = UserManager()
def __str__(self):
return self.email
def get_first_name(self):
if self.first_name:
return self.first_name
return self.first_name
def get_email(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
@property
def is_staff(self):
if self.is_admin:
return True
return self.staff
@property
def is_admin(self):
return self.admin
这是我的日志: 我已经确认 print(request.POST.get('') 返回电子邮件和密码,所以我不确定我在这里缺少什么。
web_1 | <tr><th><label for="id_email">email:</label></th><td><input type="text" name="email" class="form-control" placeholder="Email" maxlength="255" required id="id_email"></td></tr>
web_1 | <tr><th><label for="id_password">password:</label></th><td><input type="password" name="password" class="form-control" placeholder="Password" required id="id_password"></td></tr>
web_1 | Error with if form.is_valid():
web_1 | [20/Mar/2021 10:16:21] "POST /accounts/login/ HTTP/1.1" 200 3192
解决方案
我解决了。事实证明,即使所有必填字段都存在,表单也没有绑定。我尝试了很多不同的建议,但最终归结为将 form = LoginForm(request.POST) 修改为 form = LoginForm(request.POST, request.POST)。出于某种原因,有两个 request.POST 允许表单通过 is_valid 测试。我不明白为什么,因为我从未在任何教程等中看到此选项。
推荐阅读
- python - 如何更改导致烧瓶中的 TypeError 的 Python 函数
- web - 无法连接到我的应用程序服务器上的本地主机,但可以通过网络访问它
- prestashop - prestashop 自定义计算添加到基本价格
- python - 如何强制 withColumn 按时间顺序逐行工作?
- c# - 堆栈中的每个对象都为空
- delphi - TCard 类没有公开的 OnShow 和 OnHide 事件
- c - 如何使用 qsort() 但按降序排列?
- android - 生成签名的 apk 时找不到 EOCD 签名
- c++ - 为什么函数调用直接进入return语句?
- node.js - 用于更新 RTD 分支更新时间的 onWrite 触发器进入递归