【问题标题】:KeyError from customized clean() method in BaseModelFormset来自 BaseModelFormset 中自定义 clean() 方法的 KeyError
【发布时间】:2012-07-24 04:12:57
【问题描述】:

我已经阅读了大约 100 倍的 Forms 和 Formset Django 文档。为了清楚起见,这可能是我第一次使用 super() 或尝试从另一个类重载/继承(对我来说很重要。)

发生了什么事?我正在视图中制作 django-model-formset 并将其传递给模板。 formset 继承的模型恰好是 ManyToMany 关系。我希望这些关系是唯一的,因此如果我的用户正在创建一个表单并且他们不小心为 ManyToMany 选择了相同的对象,我希望它验证失败。

我相信我已经正确地编写了这个自定义“BaseModelFormSet”(通过文档),但我得到了一个 KeyError。它告诉我它找不到cleaned_data['tech'] 并且我在下面评论的行中的'tech' 一词上得到了KeyError。

模型:

class Tech_Onsite(models.Model):
    tech = models.ForeignKey(User)
    ticket = models.ForeignKey(Ticket)
    in_time = models.DateTimeField(blank=False)
    out_time = models.DateTimeField(blank=False)

    def total_time(self):
        return self.out_time - self.in_time

自定义的BaseModelFormSet:

from django.forms.models import BaseModelFormSet
from django.core.exceptions import ValidationError

class BaseTechOnsiteFormset(BaseModelFormSet):
    def clean(self):

        """ Checks to make sure there are unique techs present """

        super(BaseTechOnsiteFormset, self).clean()

        if any(self.errors):
            # Don't bother validating enless the rest of the form is valid
            return

        techs_present = []

        for form in self.forms:
            tech = form.cleaned_data['tech']  ## KeyError: 'tech' <- 

            if tech in techs_present:
                raise ValidationError("You cannot input multiple times for the same technician.  Please make sure you did not select the same technician twice.")
            techs_present.append(tech)

观点:(摘要)

## I am instantiating my view with POST data:
tech_onsite_form = tech_onsite_formset(request.POST, request.FILES)
## I am receiving an error when the script reaches:
if tech_onsite_form.is_valid():
    ## blah blah blah..

【问题讨论】:

  • 为什么不直接将 form.cleaned_data 打印到日志输出中,看看有哪些键?你确定你的表单上有一个tech 字段,并且它被称为那个字段吗?
  • @jozzas,我想这样做,但是将所有这些表单转换为字典以传递到表单并模拟所有这些过程将是一件很麻烦的事情。但是,我这样做了,发现我总共有 4 个表格,其中 2 个是空白的。当我遍历那些寻找“技术”的空白表单时,它引发了一个 KeyError。所以谢谢你鼓励我。

标签: python django django-models django-forms


【解决方案1】:

clean 方法不是缺少 return 语句吗?如果我没记错的话,它应该总是返回cleaned_data。超级调用也返回了cleaned_data,所以你应该把它分配在那里。

def clean(self):
    cleaned_data = super(BaseTechOnsiteFormset, self).clean()
    # use cleaned_data from here to validate your form
    return cleaned_data

请参阅:the django docs 了解更多信息

【讨论】:

  • 这是有道理的。我假设它在函数内部设置 self.cleaned_data 而不是返回它。我按照这个例子here,他们没有按照你的建议做。我认为它对表单集的工作方式可能不同?
【解决方案2】:

我使用 Django shell 手动调用表单。我发现我正在对视图返回的所有表单执行 clean() 方法。有2个填写了数据,2个空白。当我的 clean() 方法遍历它们时,它在到达第一个空白时返回了 KeyError。

我通过使用 try 语句并传递 KeyErrors 解决了我的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    • 2013-04-20
    • 1970-01-01
    • 2013-11-13
    • 2022-01-19
    • 1970-01-01
    相关资源
    最近更新 更多