在一个使用Django 2.0.8的Web项目中,我忘记了我的帐户密码。所以我决定使用“忘记密码”向导重置它。收到邮件并打开链接后,我到达了需要插入新密码(字段密码1)并再次确认(密码2)的表单。由于我写了两个不相等的密码(密码1=MyNewPass123),(密码2=MyNewPass12)犯了一个错误,应用程序因错误而崩溃:
ValueError at /auth/password/reset/confirm/<CODE>/set-password/
Need 2 values to unpack in for loop; got 17.
<PATH>\lib\site-packages\django\template\defaulttags.py in render, line 202
所以我回去再试一次,这次使用了两个相同(有效)的密码,结果成功了。我重复了密码重置步骤,使用了一个新密码(同样是两个不相等的输入),但是它崩溃了。
搜索任何错误或相关问题没有返回任何结果。
这里的主要问题是什么:为什么ForNode在defaulttags.py中渲染收到这么多项目,只是因为两个不相等的值…对此有什么解决方案?
ForNode在defaulttags.py:
class ForNode(Node):
child_nodelists = ('nodelist_loop', 'nodelist_empty')
def __init__(self, loopvars, sequence, is_reversed, nodelist_loop, nodelist_empty=None):
self.loopvars, self.sequence = loopvars, sequence
self.is_reversed = is_reversed
self.nodelist_loop = nodelist_loop
if nodelist_empty is None:
self.nodelist_empty = NodeList()
else:
self.nodelist_empty = nodelist_empty
def __repr__(self):
reversed_text = ' reversed' if self.is_reversed else ''
return "<For Node: for %s in %s, tail_len: %d%s>" % \
(', '.join(self.loopvars), self.sequence, len(self.nodelist_loop),
reversed_text)
def __iter__(self):
yield from self.nodelist_loop
yield from self.nodelist_empty
def render(self, context):
if 'forloop' in context:
parentloop = context['forloop']
else:
parentloop = {}
with context.push():
try:
values = self.sequence.resolve(context, True)
except VariableDoesNotExist:
values = []
if values is None:
values = []
if not hasattr(values, '__len__'):
values = list(values)
len_values = len(values)
if len_values < 1:
return self.nodelist_empty.render(context)
nodelist = []
if self.is_reversed:
values = reversed(values)
num_loopvars = len(self.loopvars)
unpack = num_loopvars > 1
# Create a forloop value in the context. We'll update counters on each
# iteration just below.
loop_dict = context['forloop'] = {'parentloop': parentloop}
for i, item in enumerate(values):
# Shortcuts for current loop iteration number.
loop_dict['counter0'] = i
loop_dict['counter'] = i + 1
# Reverse counter iteration numbers.
loop_dict['revcounter'] = len_values - i
loop_dict['revcounter0'] = len_values - i - 1
# Boolean values designating first and last times through loop.
loop_dict['first'] = (i == 0)
loop_dict['last'] = (i == len_values - 1)
pop_context = False
if unpack:
# If there are multiple loop variables, unpack the item into
# them.
try:
len_item = len(item)
except TypeError: # not an iterable
len_item = 1
# Check loop variable count before unpacking
if num_loopvars != len_item:
raise ValueError(
"Need {} values to unpack in for loop; got {}. "
.format(num_loopvars, len_item),
)
unpacked_vars = dict(zip(self.loopvars, item))
pop_context = True
context.update(unpacked_vars)
else:
context[self.loopvars[0]] = item
for node in self.nodelist_loop:
nodelist.append(node.render_annotated(context))
if pop_context:
# Pop the loop variables pushed on to the context to avoid
# the context ending up in an inconsistent state when other
# tags (e.g., include and with) push data to context.
context.pop()
return mark_safe(''.join(nodelist))
password_reset_confirm. html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block breadcrumb %}
{{ block.super }}
</h1>Password reset</h1>
{% endblock %}
{% block content %}
{% if validlink %}
<form method="post">
{% if form.errors %}
<div class="alert alert-danger">
{% for key,value in form.error_messages %}
{{ value }}<br />
{% endfor %}
{{ form.error_messages }}
{% endif %}
</div>
{% csrf_token %}
{{ form|crispy }}
<button type="submit">Submit</button>
</form>
{% else %}
<p>Wrong activation code</p>
{% endif %}
{% endblock %}
跟踪回溯:
在内部35中的文件"\lib\site-包\django\core\handler\exception.py"。响应=get_response(请求)
_get_response158中的文件"\lib\site-包\django\core\handler\base.py"。响应=self。process_exception_by_middleware(e,请求)
文件"\lib\site-包\django\core\handler\base.py"在_get_response156. response=response.渲染()
在渲染106. self.content=self.rendered_content中的文件"\lib\site-包\django\模板\response.py"
文件"\lib\site-包\django\模板\response.py"在rendered_content83中。内容=模板。渲染(上下文,自我。_request)
在渲染61中的文件"\lib\site-包\django\模板\后端\django.py"。返回self.模板.渲染(上下文)
在渲染175中的文件"\lib\site-包\django\模板\base.py"。返回自己。_render(上下文)
文件"\lib\site-包\django\test\utils.py"在instrumented_test_render98中。
在渲染943. bit=node.render_annotated(上下文)中的文件"\lib\site-packs\django\temple\base.py"
文件"\lib\site-包\django\模板\base.py"在render_annotated910中。
在渲染155中的文件"\lib\site-packs\django\temet\loader_tags.py"返回compiled_parent_render(上下文)
文件"\lib\site-包\django\test\utils.py"在instrumented_test_render98中。
在渲染943. bit=node.render_annotated(上下文)中的文件"\lib\site-packs\django\temple\base.py"
文件"\lib\site-包\django\模板\base.py"在render_annotated910中。
渲染67中的文件"\lib\site-包\django\模板\loader_tags.py"。
在渲染943. bit=node.render_annotated(上下文)中的文件"\lib\site-packs\django\temple\base.py"
文件"\lib\site-包\django\模板\base.py"在render_annotated910中。
渲染314中的文件"\lib\site-包\django\模板\defaulttags.py"。返回nodelist.渲染(上下文)
在渲染943. bit=node.render_annotated(上下文)中的文件"\lib\site-packs\django\temple\base.py"
文件"\lib\site-包\django\模板\base.py"在render_annotated910中。
渲染314中的文件"\lib\site-包\django\模板\defaulttags.py"。返回nodelist.渲染(上下文)
在渲染943. bit=node.render_annotated(上下文)中的文件"\lib\site-packs\django\temple\base.py"
文件"\lib\site-包\django\模板\base.py"在render_annotated910中。
以渲染202…格式(num_loopvars,len_item)的文件"\lib\site-包\django\模板\defaulttags.py",
异常类型:ValueError at /auth/password/reset/confirm/MzAz/set-password/Exception Value:需要2个值才能解压for循环;有17个。
经过一步一步的努力,我设法找到了问题和解决方案。
问题出在我的password_reset_confirm. html
错误所在的代码:
{% if form.errors %}
<div class="alert alert-danger">
# here it receives 17 values to unpack, but needs actually two (key, value)
{% for key,value in form.**error_messages** %}
{{ value }}<br />
{% endfor %}
{% endif %}
解决方案…
将“项目”放在表单末尾后。error_messages,我收到了一个有效的输出,没有错误。工作代码:
{% if form.errors %}
<div class="alert alert-danger">
{% for key, value in form.error_messages.items %}
{{ value }}
{% endfor %}
{% endif %}