gpt4 book ai didi

python - 如何将隐藏变量传递到 django 中的表单以便对其进行验证?

转载 作者:行者123 更新时间:2023-11-30 22:31:06 25 4
gpt4 key购买 nike

我有一张注册表,其中包含所有常见内容,但有一个机器人预防功能。我制作了一个模型 SecurityQuestion,它由两个字符域(问题和答案)组成。在注册过程中,其中一个是随机挑选的,并且应该将答案传递给表格,以便可以在那里进行验证。但是,由于我尚未弄清楚的原因,它似乎没有将答案传递给表单

让我们从代码开始

profile/forms.py

# FORM: Register an account
class UserRegistrationFirstForm(forms.ModelForm):

username = forms.CharField(max_length=20)
password = forms.CharField(widget=forms.PasswordInput)
password_confirm = forms.CharField(widget=forms.PasswordInput)
email = forms.EmailField()
email_confirm = forms.EmailField()

answer = forms.CharField(max_length=50, required=True)
hidden_answer = forms.CharField(widget=forms.HiddenInput)

class Meta:
model = User
fields = [
'username',
'email',
'email_confirm',
'password',
'password_confirm',
'answer',
]

def clean_answer(self):

formated_user_answer = self.cleaned_data.get("answer").lower()
formated_hidden_answer = self.cleaned_data.get("hidden_answer").lower()

if formated_hidden_answer != formated_user_answer:
raise forms.ValidationError("Incorect answer to security question!")

return answer

如您所见,有两个字段:answerhidden_​​answeranswer 是用户输入答案的地方,hidden_​​answer 应该在初始化表单并传递 init 时填充。

profiles/views.py

# VIEW: Register an account
def custom_register(request):

if request.user.is_authenticated():
return redirect(reverse('profile', host='profiles'))

# Grab a random registration security Q&A
qa_count = SecurityQuestion.objects.count() - 1
sec_qa = SecurityQuestion.objects.all()[randint(0, qa_count)]


# Form for users to register an account
form = UserRegistrationForm(request.POST or None, initial={"hidden_answer": sec_qa.answer,})

# Validate the registration form
if form.is_valid():

# Create new account
user = form.save(commit=False)
password = form.cleaned_data.get("password")
user.set_password(password)
user.save()

# Set the default avatar
user.profile.avatar = get_default_avatar()
user.profile.save()

login(request, user)
messages.success(request, "Welcome " + user.username + ", you have successfully registered an account!")
return redirect(reverse('pages:frontpage', host='www'))

# Context dict to return for template
context = {
"title": "Registration",
"form": form,
"question": sec_qa.question,
}
return render(request, 'profiles/register.html', context)

好吧,在注册 View 中,我随机选择一个安全问题,然后使用 initial={"hidden_​​answer": sec_qa.answer,} 将其传递到表单。然而,它似乎并没有发生,因为我收到以下错误:

'NoneType' object has no attribute 'lower'
Exception Location: path/to/profiles/forms.py in clean_answer, line 103
formated_hidden_answer = self.cleaned_data.get("hidden_answer").lower()

好的,所以 NoneType 意味着没有任何内容可以引用。我尝试了几种不同的方法来解决这个问题。我尝试将hidden_​​answer放入表单的元字段列表中。我还在模板中尝试了 {{ form.hidden_​​answer.as_hidden }} (这与我在这里想要实现的目标完全相反,因为答案仍然显示在隐藏输入的值中)页面源)。知道我做错了什么吗?

编辑:如果我正在尝试做的事情有替代方案或简单的解决方案,您能否引用有关它的任何文档?

最佳答案

发送隐藏输入并不能阻止用户知道hidden_​​answer。它在浏览器中不可见,但会很好地出现在您的 DOM 中,并且任何用户都可以访问。将答案(隐藏或不隐藏)发送到客户端本身就是一个缺陷安全性。

您应该只将问题发送到客户端(浏览器),然后在 clean() 方法中验证它。

如果我理解你的用例正确(如果我错了请纠正我),你应该这样做:

在你的views.py中,执行如下操作:

def custom_register(request):

if request.user.is_authenticated():
return redirect(reverse('profile', host='profiles'))

if request.method == 'GET':

# Grab a random registration security Q&A
qa_count = SecurityQuestion.objects.count() - 1
sec_qa = SecurityQuestion.objects.all()[randint(0, qa_count)]
#Give the text of your question to sec_qa_title. Do something like the following.
#sec_qa_title = sec_qa.title
#sec_qa_title should now have the question string of the SecurityQuestion model object instance.

form = UserRegistrationForm(initial={'question' : sec_qa_title})

#initialize whatever context variables you want.
#Rest of your code.
#return a suitable response which will display you form with the security question.


#return render(request, 'profiles/register.html', context)

if request.method == 'POST':
#All the data of form submitted by the user is inside request.POST
form = UserRegistrationForm(request.POST)

# Validate the registration form
if form.is_valid():
#Do your stuff. Return a suitable response.

else:
#Do your stuff. Return a suitable response.

现在在 forms.py 中,执行以下操作:

class UserRegistrationFirstForm(forms.ModelForm):

username = forms.CharField(max_length=20)
password = forms.CharField(widget=forms.PasswordInput)
password_confirm = forms.CharField(widget=forms.PasswordInput)
email = forms.EmailField()
email_confirm = forms.EmailField()

question = forms.CharField(max_length=50, required=True)
#removed hidden_answer field and added a question field.
answer = forms.CharField(max_length=50, required=True)

class Meta:
model = User
fields = [
'username',
'email',
'email_confirm',
'password',
'password_confirm',
#Remove the answer field.
]

def clean_answer(self):
security_question_title = self.cleaned_data.get("question")
#get the question title.
formatted_user_answer = self.cleaned_data.get("answer").lower()

#now get the SecurityQuestion model.
try:
sec_qa = SecurityQuestion.objects.get(title = security_question_title)
#Don't forget to import SecurityQuestion model.
except SecurityQuestion.DoesNotExist:
#If a user changes the question, you don't want it to fiddle with you system.
raise forms.ValidationError("Question was changed. Wrong practice.")

#Finally check the answer.
if formatted_user_answer != sec_qa.answer.lower():
raise forms.ValidationError("Incorrect answer to security question!")

return answer

有许多改进可供您稍后尝试。

例如:发送一个问题和一个 id,以便稍后通过该 id 提取问题(而不是从整个字符串中提取;有点不可靠)

我希望您理解流程并正确构建它。

由于我没有测试代码,因此可能存在一些错误,但我希望您能修复它们。

我希望这能以某种方式指导您。谢谢。

关于python - 如何将隐藏变量传递到 django 中的表单以便对其进行验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45910413/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com