Форма представления на основе классов не является ни валидной, ни невалидной (Django)
Я новичок в Django Class Based Views и не могу заставить свою форму пройти ни через form_valid(), ни через form_invalid().
Я взял большую часть этого кода из модуля Django allauth, поэтому я расширяю некоторые миксины (AjaxCapableProcessFormViewMixin & LogoutFunctionalityMixin), которые я плохо знаю.
Эта форма предназначена для того, чтобы пользователи могли изменить свой пароль после получения электронного письма. В текущем виде пользователи могут изменить пароль, но поскольку функция form_valid() никогда не срабатывает, они не перенаправляются на URL успеха, как предполагалось. Вместо этого смена пароля регистрируется, но пользователи остаются на той же странице.
Функции dispatch(), get_form_kwargs() & get_form_class() срабатывают и ведут себя так, как должны. Тем не менее, мне неясно, почему они выполняются именно в таком порядке (сначала срабатывает dispatch(), затем get_form_class() и, наконец, get_form_kwargs(). Я полагаю, что они неявно имеют порядок, представленный в этой документации: https://ccbv.co.uk/projects/Django/4.0/django.views.generic.edit/FormView/)
Мне не хватает интуиции в том, как это работает, поэтому я не знаю, есть ли способ перенаправить на URL успеха без прохождения через form_valid(), потому что это также решило бы мою проблему.
Как указано в заголовке, ни form_valid(), ни form_invalid() не срабатывают после ввода нового пароля. Последний выполненный бит кода - это return kwargs
из функции get_form_kwargs().
Вот мой код:
class PasswordResetFromKeyView(AjaxCapableProcessFormViewMixin, LogoutFunctionalityMixin, FormView):
template_name = "account/password_reset_from_key." + app_settings.TEMPLATE_EXTENSION
form_class = ResetPasswordKeyForm
success_url = '/'
reset_url_key = "set-password"
def get_form_class(self):
return get_form_class(
app_settings.FORMS, "reset_password_from_key", self.form_class
)
def dispatch(self, request, uuid, **kwargs):
self.request = request
token = get_object_or_404(ResetToken, token=uuid)
if token.redeemed == False:
self.reset_user = token.client
self.token = token
response = self.render_to_response(self.get_context_data(token_fail=False))
else:
return super(PasswordResetFromKeyView, self).dispatch(
request, uuid, **kwargs
)
return response
def get_form_kwargs(self, **kwargs):
kwargs = super(PasswordResetFromKeyView, self).get_form_kwargs(**kwargs)
kwargs["user"] = self.reset_user
if len(kwargs) > 3:
try:
if kwargs['data']['password1'] == kwargs['data']['password2']:
self.reset_user.set_password(kwargs['data']['password1'])
self.reset_user.save()
self.token.redeemed = True
self.token.date_redeemed = datetime.now()
self.token.save()
perform_login(
self.request,
self.reset_user,
email_verification=app_settings.EMAIL_VERIFICATION,
)
else:
pass
##passwords dont match
except:
##couldnt change the password
pass
return kwargs
def form_valid(self, form, **kwargs):
form.save()
return super(PasswordResetFromKeyView, self).form_valid(form)
def form_invalid(self, form):
response = super().form_invalid(form)
if self.request.accepts('text/html'):
return response
else:
return JsonResponse(form.errors, status=400)
Спасибо всем за помощь!
Если оба метода не срабатывают, это означает, что ваш requests.method никогда не будет 'POST'.
Класс FormView вызывает эти два метода, только если post.method == 'POST':
# code from django.views.generic.edit
...
def post(self, request, *args, **kwargs):
"""
Handle POST requests: instantiate a form instance with the passed
POST variables and then check if it's valid.
"""
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
Кстати в dispatch
, если token.redeemed == False
вы должны вернуть self.form_invalid()
.