【问题标题】:Catching validation errors in django forms在 django 表单中捕获验证错误
【发布时间】:2012-01-25 21:52:05
【问题描述】:

我有两个模型:

class Studio(models.Model):
    name = models.CharField("Studio", max_length=30, unique=True)

class Film(models.Model):
    studio = models.ForeignKey(Studio, verbose_name="Studio")
    name = models.CharField("Film Name", max_length=30, unique=True)

我有一个电影表单,它允许用户选择一个预先存在的工作室,或者输入一个新的工作室(在 earlier question 的帮助下:

class FilmForm(forms.ModelForm):
    required_css_class = 'required'
    studio = forms.ModelChoiceField(Studio.objects, required=False, widget = SelectWithPlus)
    new_studio = forms.CharField(max_length=30, required=False, label = "New Studio Name", widget = DeSelectWithX(attrs={'class' : 'hidden_studio_field'}))

    def __init__(self, *args, **kwargs):
        super(FilmForm, self).__init__(*args,**kwargs)
        self.fields['studio'].required = False

    def clean(self):
        cleaned_data = self.cleaned_data
        studio = cleaned_data.get('studio')
        new_studio = cleaned_data.get('new_studio')

        if not studio and not new_studio:
            raise forms.ValidationError("Must specify either Studio or New Studio!")
        elif not studio:
            studio, created = Studio.objects.get_or_create(name = new_studio)
            self.cleaned_data['studio'] = studio

        return super(FilmForm,self).clean()

    class Meta:
        model = Film

现在,我的第一个问题是,当 studio 和 new_studio 都丢失时 我得到一个 django ValueError: Cannot assign None: "Film.studio" does not allow null values 错误。我以为我是捕获所有错误,因此 django 永远不会意识到 Film.studio 是空的。

第二个问题是操作顺序。 如果我只想在确定 FilmForm 的其余部分有效后才保存 new_studio(从而防止在完整的电影条目通过之前保存一堆工作室名称)? 我是还是我会冒着提前保存的风险,因为 new_studio 保存在表单的清理中?

编辑:添加 Traceback 并编辑验证 if 语句

【问题讨论】:

  • 检查此行是否符合您的意思:if studio is None and new_studio == '':。工作室可以是'' 还是new_studio 是None?如果将其更改为if not (studio or new_studio):,它是否正确显示表单错误?
  • 我在 ValidationError 之前放了一个打印“here”。它出现在终端中,因此我可以确认代码已到达该部分。我尝试按照您的建议更改标准并得到相同的错误
  • 你能粘贴回溯吗?
  • 为什么要更改ifelif 检查?你现在使用的那个在逻辑中打开了漏洞,允许某些场景不受控制地通过。应该坚持我给你的。此外,clean 方法仅在单独的 clean_FIELD 方法运行后运行,因此有效地,只有在其他一切都有效时才能到达这一点。当表单中仍有其他问题时,您不必担心创建工作室。
  • -ChrisPratt:公平点。前几次我运行它时,我无法让实例正常工作。可能是用户错误。上面编辑过,但我仍然有同样的问题

标签: django django-forms


【解决方案1】:

从cleaned_data 中删除studionew_studio

    if not studio and not new_studio:
        del cleaned_data['studio'], cleaned_data['new_studio']
        raise forms.ValidationError("Must specify either Studio or New Studio!")

【讨论】:

  • 优秀。这行得通。关于如何防止在表单的其余部分完全验证之前创建 new_studio 的任何输入?如果我输入了 new_studio,但省略了电影名称,则表单不会通过,因为名称是必需的,但无论如何都会创建 new_studio。
  • 您可以将elif 更改为更具体。检查 studiofilm 是否在 cleaned_data 中,然后仅在一切有效的情况下创建新 Studio。
【解决方案2】:

关于防止预先保存 new_studio 的仅供参考:

新的 def clean 形式: def 清洁(自我): 清理数据 = self.cleaned_data 工作室 = clean_data.get('studio') new_studio = clean_data.get('new_studio')

    if not studio and not new_studio:
        del cleaned_data['studio'], cleaned_data['new_studio']
        raise forms.ValidationError("Must specify either Studio or New Studio!")
    elif not studio:
        del cleaned_data['studio']

    return super(FilmForm,self).clean()

在视图中:

def testone(request):
    if request.method == 'POST': # If the form has been submitted...
        form = FilmForm(request.POST) # A form bound to the POST data

        if form.is_valid(): # All validation rules pass
            if form.cleaned_data['new_studio']:
                studio, created = Studio.objects.get_or_create(name = form.cleaned_data['new_studio'])
                new_film = form.save(commit=False)
                new_film.studio = studio
            else:
                new_film = form

            new_film.save()
            return HttpResponseRedirect('/') # Redirect after POST
        else:
            form = FilmForm() # An unbound form

        return render_to_response('testone.html', {
            'form': form
        }, context_instance=RequestContext(request))

【讨论】:

    猜你喜欢
    • 2016-03-20
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多