【问题标题】:Issues with two forms submission in django one after another在 django 中一个接一个提交两个表单的问题
【发布时间】:2020-05-27 12:51:30
【问题描述】:

我正在处理忘记密码页面,用户首先必须回答启用文本字段以创建新密码的问题。

这里,我有两种形式,一种是安全问题,另一种是密码和确认密码。

下面是我的forms.py

from django import forms
from .models import SecurityQuestions

class PasswordForm(forms.Form):
    password = forms.CharField(disabled=True, widget=forms.PasswordInput(attrs={'placeholder':'New Password'}))
    password_confirm = forms.CharField(disabled=True, widget=forms.PasswordInput(attrs={'placeholder':'Re-enter Password'}))

    def clean(self, *args,**kwargs):
        password = self.cleaned_data.get('password')
        password_confirm = self.cleaned_data.get('password_confirm')

        if password and password_confirm:
            if password != password_confirm:
                raise forms.ValidationError('Password Mismatch')
        return super(PasswordForm, self).clean(*args, **kwargs)

class PasswordVerificationForm(forms.Form):
    question = forms.ModelChoiceField(queryset=SecurityQuestions.objects.all(), empty_label=None, widget=forms.Select(attrs={'class':'form-control','id': 'sectxt'}))
    answer = forms.CharField(label='answer', widget=forms.TextInput(attrs={'placeholder':'Answer','id': 'anstxt'}))

以下是我的观点.py

from django.shortcuts import render, redirect
from .forms import PasswordForm, PasswordVerificationForm
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.hashers import make_password
from .models import SecurityQuestions
from django.contrib import messages

@login_required
@csrf_exempt
def password_reset(request):
    form = PasswordForm(request.POST or None)
    form1 = PasswordVerificationForm(request.POST or None)
    if request.method == 'POST':
        if request.POST.get("verify", False):
            question = request.POST.get('question')
            answer = request.POST.get('answer')
            print("question",question)
            print("answer",answer)
            check = SecurityQuestions.objects.get(id=question) #id=1
            print(check.answer)
            if check.answer == answer:
                messages.success(request, 'Enter Your New Password', 'alert-success')
                form.fields['password'].disabled = False
                form.fields['password_confirm'].disabled = False
            else:
                redirect('/')
                messages.error(request, 'Incorrect Answer', 'alert-danger')
        if request.POST.get("create", False):
            if form.is_valid():
                print("For Changing Password...")
                password = form.cleaned_data.get('password')
                request.user.password = make_password(password)
                request.user.save()
                return redirect('/')
    else:
        form = PasswordForm()
        form1 = PasswordVerificationForm()
    return render(request,"forget_password.html", {"form": form, "form1":form1})

以下是我的忘记密码.html

<div class="container">
        <div class="main">
            <div class="row justify-content-center">
                <div class="col-md-4">
                        <div class="login-form">
                            <div class="row">

                                <div class="col-md-12">
                                    <div class="login-title-holder">
                                        <h4>Forgot Password</h4>
                                    </div>
                                </div>
                                <form method="post">
                                <div class="form-group col-md-12">
                                <div class="input-group">
                                  {{ form1.question | add_class:'form-control' }}
                                  <span class="input-group-append">
                                        <div class="input-group-text input-group-icon"><i class="fa fa-question" aria-hidden="true"></i></div>
                                    </span>
                                </div>
                            </div>
                            <div class="form-group col-md-12">
                                    <div class="input-group">
                                        {{ form1.answer | add_class:'form-control' }}
                                        <span class="input-group-append">
                                            <div class="input-group-text input-group-icon  "><i class="fa fa-comment" aria-hidden="true"></i></div>
                                        </span>
                                    </div>
                                </div>

                            <div class="col-md-12">
                                 {% if messages %}
                                    {% for message in messages %}
                                        <div {% if message.tags %} class="alert {{ message.tags }} text-center"{% endif %}>
                                            <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
                                            {{ message }}
                                        </div>
                                    {% endfor %}
                                {% endif %}
                            <input type="submit" name = "verify" formmethod="post" style="visibility: hidden;">
                        </div>
                        </form>
                        <form method="post">
                                <div class="form-group col-md-12">
                                    <div class="input-group">
                                        {{ form.password | add_class:'form-control' }}
                                        <span class="input-group-append">
                                            <div class="input-group-text input-group-icon"><i class="fa fa-key" aria-hidden="true"></i></div>
                                        </span>

                                    </div>
                                </div>
                                <div class="form-group col-md-12">
                                    <div class="input-group">
                                        {{ form.password_confirm | add_class:'form-control' }}
                                        <span class="input-group-append">
                                            <div class="input-group-text input-group-icon"><i class="fa fa-key" aria-hidden="true"></i></div>
                                        </span>

                                    </div>
                                </div>


                                <div class="col-md-12">
                                    <div class="button-holder">
                                        <a href="index.html" class="login-btn">Cancel</a>
                                        <button class="login-btn" type="submit" formmethod="post" name="create">Create</button>
                                    </div>
                                </div>
                            </form>
                            </div>
                            </div>
                </div>
            </div>
        </div>
    </div>

如果我首先输入安全答案,根据条件,如果为真,它会启用密码和密码确认的文本字段。 但它不是创建新密码。 但是,如果我在PasswordForm 中更改disabled = False,那么它会成功创建新密码。 我想知道为什么第一个表单执行成功后它没有执行代码。

谢谢!

【问题讨论】:

  • 我没有看到“创建”和“验证”字段。
  • 嗨,我已经添加了我的 forget_password.html 代码。在这里你可以找到你需要的东西。但是,create 和 verify 是输入 type="submit" 的名称,以了解何时执行什么表单。谢谢。
  • 您的模板中有几个嵌套问题。你不能nest forms 我认为你想至少在第一个表格之后结束这一行。先解决这些问题,然后看看你在哪里。
  • 感谢您让我了解嵌套表单,我已将表单标签替换为 div 标签,现在不再出现嵌套表单问题。但我的主要问题仍然没有解决。

标签: django django-models django-rest-framework django-forms django-views


【解决方案1】:

您确实应该将其链接到 2 个 url,而不是在一页中尝试 2 个表单。您只能提交一份表格,这就是您面临的问题。提交安全问题后,再次实例化表单并禁用字段:

form = PasswordForm(request.POST or None)

现在它们没有启用,因为 form1 中名为“验证”的提交按钮不再存在,因此该分支中的代码没有执行。

假设 url 是 /password_reset/ - 粗略的轮廓(未经测试):

@login_required
@csrf_exempt
def security_question(request):
    form = PasswordVerificationForm(request.POST)
    if request.method == 'POST':
        if form.is_valid():
             token = generate_strong_token()  # Implement: generate a strong token, url safe
             request.session["password_reset_token"] = token
             return redirect(f'/password_reset/{token}/')
    else:
        return render(...)

@login_required
@csrf_exempt
def change_password(request, **kwargs):
    form = PasswordForm(request.POST)
    token = request.session.get('password_reset_token')
    if token == kwargs['token']:
        if request.method == 'POST' and form.is_valid():
            del request.session['password_reset_token']

            # handle password change and redirect to wherever
        else:
            return render(...)
    else:
        raise SecurityError('Invalid token')

你的网址应该是这样的:

urlpatterns = [
    re_path('password_reset/(?P<token>[0-9A-F]{32})/', change_password)
    path('password_reset/', security_question)
]

【讨论】:

    猜你喜欢
    • 2022-07-18
    • 2017-12-24
    • 1970-01-01
    • 2015-06-13
    • 2014-05-14
    • 2015-06-30
    • 1970-01-01
    • 2010-10-07
    相关资源
    最近更新 更多