【问题标题】:Django forms keyerror on ModelChoiceFieldDjango 在 ModelChoiceField 上形成 keyerror
【发布时间】:2012-04-20 14:37:50
【问题描述】:

我有一个用于高级搜索的表单。其中一个字段,island_group 是一个 ModelChoiceField,我为其返回一个 values_list 作为查询集(以便只获取每个不同的值一次)。

forms.py:

class SearchForm(forms.Form):
    ...
    island_group = forms.ModelChoiceField(
        required=False,
        queryset=Locality.objects.values_list('islandgroup', flat=True).distinct('islandgroup')
    ...

因为这会引发invalid choice 的错误,因为我使用的是值而不是对象,所以我覆盖了错误:

    def clean(self):
        cleaned_data = super(SearchForm, self).clean()

        if self._errors["island_group"]:
            del self._errors["island_group"]

        return cleaned_data

但是,我不断收到KeyError at /collections/ 'island_group' 错误。事实上,由于这些数据是从只读数据库中提取的,我只是希望能够以最小的麻烦将其传递到视图中。

任何帮助将不胜感激。另外,这是回溯:

Traceback:
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/home/sam/django-projects/datazone/bin/datazone/cdrs/views.py" in cdrs_index
  59.     return render(request, 'cdrs_index.html', context)    
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/shortcuts/__init__.py" in render
  44.     return HttpResponse(loader.render_to_string(*args, **kwargs),
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/loader.py" in render_to_string
  188.         return t.render(context_instance)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in render
  123.             return self._render(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/test/utils.py" in instrumented_test_render
  57.     return self.nodelist.render(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in render
  744.                 bits.append(self.render_node(node, context))
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in render_node
  757.         return node.render(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  127.         return compiled_parent._render(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/test/utils.py" in instrumented_test_render
  57.     return self.nodelist.render(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in render
  744.                 bits.append(self.render_node(node, context))
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in render_node
  757.         return node.render(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  64.             result = block.nodelist.render(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in render
  744.                 bits.append(self.render_node(node, context))
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in render_node
  757.         return node.render(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/defaulttags.py" in render
  227.                 nodelist.append(node.render(context))
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in render
  792.             output = self.filter_expression.resolve(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in resolve
  510.                 obj = self.var.resolve(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in resolve
  653.             value = self._resolve_lookup(context)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/template/base.py" in _resolve_lookup
  683.                         current = getattr(current, bit)
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/forms/forms.py" in _errors
  415.         return self.form.errors.get(self.name, self.form.error_class())
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/forms/forms.py" in _get_errors
  112.             self.full_clean()
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/forms/forms.py" in full_clean
  268.         self._clean_form()
File "/home/sam/django-projects/datazone/local/lib/python2.7/site-packages/django/forms/forms.py" in _clean_form
  296.             self.cleaned_data = self.clean()
File "/home/sam/django-projects/datazone/bin/datazone/cdrs/forms.py" in clean
  113.         if self._errors["island_group"]:

Exception Type: KeyError at /collections/
Exception Value: 'island_group'

【问题讨论】:

    标签: django forms


    【解决方案1】:

    更新

    我想我知道你的例外情况,它可能看起来像 Select a valid choice. That choice is not one of the available choices. 对吧? 原因是您传递给queryset=Locality.objects.values_list('islandgroup', flat=True).distinct('islandgroup')ValuesListQuerySet 而不是QuerySetValueListQuerySet 实例不包含_meta 信息并用作普通列表,这会导致ModelChoiceField 生成错误的表单选项。就像下面这个人为的例子

    >>> from django import forms
    >>> from django.contrib.auth.models import *
    
    >>> class F(forms.Form):
    ...     user = forms.ModelChoiceForm(queryset=User.objects.values_list('username', flat=True))
    
    >>> print F().as_p()
    <p><label for="id_user">User:</label> <select name="user" id="id_user">
    <option value="" selected="selected">---------</option>
    <option value="okm">okm</option>
    </select></p>
    

    但是,第二个选项的正确值应该是用户okm的pk,就像

    >>> class F(forms.Form):
    ...     user = forms.ModelChoiceForm(queryset=User.objects)
    
    >>> print F().as_p()
    <p><label for="id_user">User:</label> <select name="user" id="id_user">
    <option value="" selected="selected">---------</option>
    <option value="1">okm</option>
    </select></p>
    

    因此您需要根据islandgroup 模型字段的类型更改代码中的island_group = 行。

    除了上面的问题,你的代码都很好。因此,当self._errors 中没有其他'island_group' 验证错误时,self._errors["island_group"] 会引发 KeyError。

    【讨论】:

    • 所以当我删除我的自定义清理方法时会弹出invalid choice 错误。如果在该字段中未选择任何内容,则该字段通过验证,但是一旦我选择了某些内容,就会引发错误。我猜这是因为这些是字符串值而不是对象?所以基本上我只需要 Django 停止让我失望,因为它们不是对象,而自定义的 clean 方法是我想出的最好的方法。我不确定我是否理解您的第三段 - 为什么检查 self._errors["island_group"] 的存在会引发 KeyError?
    • @DarwinTech 我的意思是KeyError 是一个Python 异常,就像{}['key'] 引发的异常一样。你可以通过{}.get('key')if 'key' in {}: {}['key'] 来避免它
    • 好的。这适用于自定义清理方法:if "island_group" in self._errors: del self._errors["island_group"]。我想发布 invalid choice 验证错误的堆栈跟踪 - 当 Django 没有失败时我如何访问它(它只是返回那个错误)?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 2014-04-29
    • 2013-02-19
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    相关资源
    最近更新 更多