摘要:我的自定义登录表单无法根据.is_valid((进行验证;密码值被传递到views.py,因为print(request.POST.get(''(返回电子邮件(登录所需(和密码。
我认为我的问题与其他类似的问题不同,因为它们似乎都解决了缺失的必填字段。我尝试从.is_valid中排除我能想到的所有字段,但表单无法验证。
我点击按钮,什么也没发生(数据移动,这很奇怪,因为表单仍然没有验证验证,我的登录也不起作用——请参阅底部的日志(。我使用的是Django 3.7。
账户/表格.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")
账户/网址.py
app_name = 'accounts'
from .views import login_page
urlpatterns = [
path('login/', login_page, name="login")
]
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
以下是我的日志:我已经确认打印(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=LoginCorm(request.POST,request.POST(。出于某种原因,有两个请求。POST允许表单通过is_valid测试。我不明白为什么,因为我从来没有在任何教程中看到过这个选项,等等