【问题标题】:Django widgets: too many values to unpackDjango 小部件:解包的值太多
【发布时间】:2014-12-04 12:13:13
【问题描述】:

我正在尝试为我的 customUser 模型的选定用户创建版本表单,但不幸的是,这是我在获取表单时得到的:

ValueError at /changeCustomUser/ too many values to unpack    

跟踪我到模板和视图文件 - 我会在代码错误的地方标记。

models.py

class CustomUserManager(UserManager):
    def create_user(self, username, email=None, password=None, **extra_fields):
        return UserManager.create_user(self, username, email=email, password=password, **extra_fields)

    def create_superuser(self, username, email, password, **extra_fields):
        return UserManager.create_superuser(self, username, email, password, **extra_fields)

class CustomUser(AbstractUser):
    role = models.CharField(max_length = 1, default = 'C')

    objects = CustomUserManager()

    class Meta(AbstractUser.Meta):
        swappable = 'My_app.CustomUser'

forms.py

class CustomUserChangeForm(UserChangeForm):
    def __init__(self, choices_list, *args, **kwargs):
        super(CustomUserChangeForm, self).__init__(*args, **kwargs)
        if choices_list:
            self.fields['role']=forms.ChoiceField(label='Function', choices=choices_list, widget=forms.Select, required = True)
        del self.fields['password']
        del self.fields['username']

    class Meta(UserChangeForm.Meta):
        model = CustomUser
        fields = ('first_name', 'role')

views.py

def changeCustomUser(request):
    if request.method == 'POST':
        customUserChangeForm = CustomUserChangeForm(request.POST, instance=request.user)
        if customUserChangeForm.is_valid():
            customUserChangeForm.save()
            return HttpResponseRedirect('/changeCustomUser/?customUser=saved')
        else:
            e1 = str(request.user)
            if e1 == 'AnonymousUser':
                context1={'welcome_id': 'Welcome Guest :)', 'form': 'Log in to change user details', 'error': ''}
            else:
"""ERROR TRACE"""
                context1={'welcome_id': 'Welcome '+request.user.first_name + ' :)', 'form': customUserChangeForm,'error': 'Make data valid'}
            return render_to_response('changeCustomUser.html', context1 ,context_instance=RequestContext(request)) 
    else:
        e1 = str(request.user)
        if e1 == 'AnonymousUser':
            context1={'welcome_id': 'Welcome Guest', 'error': ''}
        else:
            if request.user.role == 'A':
                customUserChangeForm = CustomUserChangeForm(initial = {'first_name': request.user.first_name, 'role': request.user.role}, 
                choices_list=[('A', 'B', 'C')]
                )
            elif request.user.role == 'B':
                customUserChangeForm = CustomUserChangeForm(initial = {'first_name': request.user.first_name, 'role': request.user.role}, 
                choices_list=[('B', 'C')]
                )

            if request.GET.get('customUser', '') == 'saved':
                context1={'welcome_id': 'Welcome '+request.user.first_name + ' :)', 'form': customUserChangeForm,'error': 'Details changed succesfully.'}
            else:
                context1={'welcome_id': 'Welcome '+request.user.first_name + ' :)', 'form': customUserChangeForm,'error': ''}        # SECOND ERROR TRACE
        return render_to_response('changeCustomUser.html', context1 ,context_instance=RequestContext(request))

更改CustomUser.html

{# Other fields declared as follows, but without role conditions: #}
{% if user.role == "A" or user.role == "B" %}
    <tr>
        <td>{{ form.role.label_tag }}</td>
"""ERROR TRACE"""
        <td>{{ form.role }}</td>
    </tr>
{% endif %}

如您所见,我在“角色”字段中设置了自己的权限,不同的角色可以执行不同的更改。回到问题: 我尝试通过从前一个视图传递一个变量来切换 request.user 一段时间:

if request.GET.get('username_get', '') != '':
    sub_user = Reader.objects.get(username=str(request.GET.get('username_get', '')))
else:
    sub_user = request.user

这至少帮助我显示了我选择更改的用户的正确数据。可悲的是 - 用户切换只持续到我点击 POST,因为丢失了这个传递的参数,并且与上面给出的错误结果相同(解包的值太多)。我设法得到的只是编辑登录用户而不是我选择编辑的用户。 我当然试图弄清楚为什么这些值是错误的,但网络搜索只确认它们需要保持元组格式,以便选择小部件可以处理它们。 任何想法如何对具有“A”/“B”角色的选定用户进行操作?

编辑:我的错。对不起,不小心。我在上面说的是元组,但没有提供元组。就像你说的那样,我得到了它们:

choices_list=[('A','A'),  ('B','B'), ('C', 'C')]    

单一选择列表也不起作用。感谢您提供非常有用的提示。我会立即改进我的代码。由于choices_list 的特定部分没有问题 - 下面是完整的追溯:

Environment:
Request Method: POST
Request URL: http://localhost:8000/changeCustomUser/
Django Version: 1.7.1
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'My_app')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware')


Template error:
In template /var/www/html/DjangoApps/My_app/templates/changeCustomUser.html, error at line 22
   too many values to unpack
   16 :     <td>{{ form.email.label_tag }}</td>
   17 :     <td>{{ form.email }}</td>
   18 : </tr>
   19 : {% if user.role == "A" or user.role == "B" %}
   20 : <tr>
   21 :     <td>{{ form.role.label_tag }}</td>
   22 :     <td> {{ form.role }} </td>
   23 : </tr>
   24 : {% endif %}
   25 : <tr>
   26 :     <td>{{ form.user_address.label_tag }}</td>
   27 :     <td>{{ form.user_address }}</td>
   28 : </tr>
   29 : </table>

Traceback:
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/core/handlers/base.py" in get_response
  111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/var/www/html/DjangoApps/My_app/views.py" in changeCustomUser
  88.             return render_to_response('changeCustomUser.html', context1 ,context_instance=RequestContext(request)) 
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/shortcuts.py" in render_to_response
  23.     return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/loader.py" in render_to_string
  178.         return t.render(context_instance)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/base.py" in render
  148.             return self._render(context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/base.py" in _render
  142.         return self.nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/base.py" in render
  844.                 bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/debug.py" in render_node
  80.             return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/loader_tags.py" in render
  126.         return compiled_parent._render(context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/base.py" in _render
  142.         return self.nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/base.py" in render
  844.                 bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/debug.py" in render_node
  80.             return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/loader_tags.py" in render
  65.                 result = block.nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/base.py" in render
  844.                 bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/debug.py" in render_node
  80.             return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/defaulttags.py" in render
  312.                 return nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/base.py" in render
  844.                 bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/debug.py" in render_node
  80.             return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/template/debug.py" in render
  93.             output = force_text(output)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/utils/encoding.py" in force_text
  85.                 s = six.text_type(s)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/forms/forms.py" in __str__
  508.         return self.as_widget()
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/forms/forms.py" in as_widget
  560.         return force_text(widget.render(name, self.value(), attrs=attrs))
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/forms/widgets.py" in render
  504.         options = self.render_options(choices, [value])
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.1-py2.7.egg/django/forms/widgets.py" in render_options
  530.         for option_value, option_label in chain(self.choices, choices):

Exception Type: ValueError at /changeCustomUser/
Exception Value: too many values to unpack    

PS 发现三个错别字。抱歉,经过一整夜的努力让它发挥作用,我可能没有像我应该的那样专注。

【问题讨论】:

    标签: python django django-models django-forms


    【解决方案1】:

    请发布 full 回溯 - 但我怀疑您的问题出在这一行:

     choices_list=[('A', 'B', 'C')]
    

    选择列表应该是(value, label) 对的序列(列表或其他)。将以上内容替换为:

     choices_list=[('A','A'),  ('B','B'), ('C', 'C')]
    

    还有这个(它被解释为一个带有值'B'和标签'C'的单选列表):

    choices_list=[('B', 'C')]
    

    与:

    choices_list=[('B', 'B'), ('C', 'C')]
    

    附注:

    阅读有关 django auth 和 request.user 的文档:您可以替换它

    e1 = str(request.user)
    if e1 == 'AnonymousUser':
        do_something()
    

    if request.user.is_anonymous():
        do_something()
    

    学习使用 python 的字符串格式化功能 - 你可以替换这个:

    'Welcome '+request.user.first_name + ' :)'
    

    'Welcome %s :)' % request.user.first_name
    

    或更好:将演示文稿留给模板层(它所属的地方),请记住,使用默认设置,您可以在模板上下文中访问request.user,而无需显式传递它。

    学会正确地分解代码以避免重复:您将相同的代码块复制粘贴到不同的地方,这充其量是脆弱的(FWIW 您已经有一个地方有错字,看看您能不能找到它)。

    最后:学习使用 Django 的消息应用程序 (https://docs.djangoproject.com/en/1.6/ref/contrib/messages/) 而不是重新发明方轮。

    【讨论】:

    • 编辑部分添加了完整的回溯。问题依然存在。还有其他想法吗?
    • 错误出现在“for option_value, option_label in chain(self.choices,choices”...您显然在某处仍然有错误的选择列表。如果您不知道最好的选择在哪里可能是在 Django 的源代码中围绕该行添加一些调试代码。
    【解决方案2】:

    最后 - 我赢得了那场战斗。

    在我之前的构建中它无权正常工作。

    首先 - 我需要在我的 POST request.method "if" 块中创建变量 "choices_list"。这是克劳。然后,只有这样我才能创建我的 customUserChangeForm,在构造函数中再添加一个参数:

    customUserChangeForm = CustomUserChangeForm(choices_list, request.POST, instance=sub_user)
    

    最后要做的是将正在编辑的用户的用户名从 GET 参数传递到此“if”,并为正确的用户名创建 sub_user 的实例,并匹配正确的选择列表值。

    再次感谢您的帮助和提示。

    PS 错误回溯并不像它应有的那样具体,实际上指向 views.py 文件中的错误位置。

    【讨论】:

      猜你喜欢
      • 2019-06-07
      • 2012-02-15
      • 1970-01-01
      • 2017-10-17
      • 2010-10-29
      • 1970-01-01
      • 2016-04-02
      • 2020-05-11
      • 2019-07-11
      相关资源
      最近更新 更多