Как исправить перезапись CSRF TOKEN данными формы после неудачной отправки в django?
Я создаю проект мультитенантов, используя django-тенант и django-тенант-пользователь, но сталкиваюсь со странной проблемой, когда поля CSRF TOKEN и email в моей форме входа перезаписываются данными пароля после неудачной попытки входа.
Пожалуйста, просмотрите мои релевантные фрагменты кода ниже:
View
def login_user(request):
if request.user.is_authenticated:
return redirect('core:index')
if request.method != 'POST':
form = LoginForm()
return render(request, 'core/login.html', {'form': form})
form = LoginForm(request.POST)
if not form.is_valid():
context = {"form": form}
if not form.errors:
messages.error(request, 'Invalid username or password')
return render(request, 'core/login.html', context)
user = authenticate(request, username=form.cleaned_data['username'], password=form.cleaned_data['password'])
if user is None:
messages.error(request, 'Invalid username or password.')
return render(request, 'core/login.html', {'form': form})
messages.success(request, 'Login successful')
login(request, user)
return redirect('core:index')
Форма
class LoginForm(forms.Form):
username = forms.CharField(min_length=4, max_length=150)
password = forms.CharField(min_length=4, max_length=128, widget=forms.PasswordInput)
Шаблон
{% extends "_base.html" %}
{% block title %}
<title>TalwaPro HR Admin - Login </title>
{% endblock title %}
{% block content %}
{% load tailwind_filters %}
<div class="flex h-screen items-center justify-center">
<div class="card w-[90%] bg-base-200 shadow-xl justify-center md:w-[65%] lg:w-[40%]">
{% if messages %}
<div class="toast toast-top toast-start">
<div class="alert alert-error">
{% for message in messages %}
{{ message }}
{% endfor %}
</div>
</div>
{% endif %}
<div class="card-body">
<h2 class="card-title text-accent justify-center">Sign In</h2>
<form class="mt-4" action="/login/" method="POST">
{% csrf_token %}
<label class="input input-bordered flex items-center gap-2 {% if form.username.errors %} border-error {% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-4 h-4 opacity-70"><path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12.735 14c.618 0 1.093-.561.872-1.139a6.002 6.002 >
<input type="text" class="grow" name="username" value="{% if form.username.value %} {{form.username.value}} {% endif %}" placeholder="Username" required />
</label>
<div class="text-error">
{% if form %}
{{ form.username.errors }}
{% endif %}
</div>
<label class="input input-bordered flex items-center gap-2 mt-4 {% if form.password.errors %} border-error {% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-4 h-4 opacity-70"><path fill-rule="evenodd" d="M14 6a4 4 0 0 1-4.899 3.899l-1.955 1.955a.5.5 0 0 1-.353.146H5v1>
<input type="password" class="grow" name="password" placeholder="Password" required />
</label>
<div class="text-error">
{% if form %}
{{ form.password.errors }}
{% endif %}
</div>
<div class="card-actions justify-center mt-4">
<button class="btn btn-primary" type="submit">Sign In</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
Я пробовал регистрировать данные формы, но это не помогло, поскольку CSRF TOKEN передается правильно при первой попытке, а при других запросах в качестве CSRF TOKEN передаются данные пароля
Описанная вами проблема похожа на ситуацию, когда django.middleware.csrf.CsrfViewMiddleware
не полностью активирован в настройках. Если полная установка промежуточного программного обеспечения нежелательна, вы можете рассмотреть возможность декорирования представления с помощью csrf_protect
.
Ref: https://docs.djangoproject.com/en/5.0/ref/csrf/
Я также хотел бы предложить вам рефакторинг вашего приложения для использования AuthenticationForm
через LoginView
Django, который использует современные представления на основе классов, позволяя вам делегировать большую часть этих функций обратно в сам Django.