【问题标题】:Django is validating formset that has no value selected for required fieldDjango 正在验证没有为必填字段选择值的表单集
【发布时间】:2020-04-16 23:46:13
【问题描述】:

我刚刚开始玩表单集。不知道我现在在做什么。 我已经到了将带有 formset 的表单保存到数据库中的地步。但是,如果没有为必填字段“ledger”选择任何内容,则验证仍然通过,Django 会抛出“Key error”。

我的forms.py:

class JournalEntryForm(forms.Form):
    date = forms.DateField(widget=DateTypeInput())
    description = forms.CharField(required=False)

class LineItemForm(forms.Form):
    ledger = forms.ModelChoiceField(queryset=Ledger.objects.all())
    description = forms.CharField(required=False)
    project = forms.ModelChoiceField(queryset=Project.objects.all(), required=False)
    cr = forms.DecimalField(decimal_places=2, required=False)
    dr = forms.DecimalField(decimal_places=2, required=False)

views.py 中的函数。我已经标记了第 33 行,这是发生“关键错误”的行。

@login_required
def entries_new(request):

    # Takes form and returns form set. So we now have a form set.
    LineItemFormSet = formset_factory(LineItemForm, extra=2)

    if request.method == 'POST':
        journal_entry_form = JournalEntryForm(request.POST)
        lineitem_formset = LineItemFormSet(request.POST)

        if journal_entry_form.is_valid() and lineitem_formset.is_valid():
            q0 = JournalEntry(user=request.user, date=journal_entry_form.cleaned_data['date'], type="JE")
            q0.save()

            for lineitem_form in lineitem_formset:
                q1 = LineItem(
                    journal_entry=q0,
                    ledger=lineitem_form.cleaned_data['ledger'], #<---- This is line 33 referenced in the error
                    cr=lineitem_form.cleaned_data['cr'],
                    dr=lineitem_form.cleaned_data['dr'],
                    project=lineitem_form.cleaned_data['project'],
                    )
                q1.save()

            messages.success(request, "Journal entry successfully saved.")
            return HttpResponseRedirect(reverse('journal:entries_show_all') )
    else:
        journal_entry_form = JournalEntryForm()
        lineitem_formset = LineItemFormSet()

    context = { 'journal_entry_form': journal_entry_form, 'lineitem_formset': lineitem_formset, }

    return render(request, 'journal/entries_new.html', {'journal_entry_form': journal_entry_form, 'lineitem_formset': lineitem_formset})

我在浏览器中遇到的错误:

KeyError at /journal/entries/new/
'ledger'
Request Method: POST
Request URL:    http://localhost/journal/entries/new/
Django Version: 3.0
Exception Type: KeyError
Exception Value:    
'ledger'
Exception Location: C:\Users\Philip\CodeRepos\Acacia2\Journal\views.py in entries_new, line 33
Python Executable:  C:\Users\Philip\CodeRepos\Acacia2\venv\Scripts\python.exe
Python Version: 3.8.0
Python Path:    
['C:\\Users\\Philip\\CodeRepos\\Acacia2',
 'C:\\Users\\Philip\\AppData\\Local\\Programs\\Python\\Python38-32\\python38.zip',
 'C:\\Users\\Philip\\AppData\\Local\\Programs\\Python\\Python38-32\\DLLs',
 'C:\\Users\\Philip\\AppData\\Local\\Programs\\Python\\Python38-32\\lib',
 'C:\\Users\\Philip\\AppData\\Local\\Programs\\Python\\Python38-32',
 'C:\\Users\\Philip\\CodeRepos\\Acacia2\\venv',
 'C:\\Users\\Philip\\CodeRepos\\Acacia2\\venv\\lib\\site-packages']
Server time:    Thu, 26 Dec 2019 20:42:45 +0000

【问题讨论】:

  • 您是否尝试在 Lineitemform 中明确设置 ledger required =True?

标签: django django-forms


【解决方案1】:

因此,经过一番挖掘,事实证明 Django 不会验证任何空表单集。我在表单中添加了以下 init,现在如果提交了空表单集,我会收到一个不错的表单错误:

class LineItemForm(forms.Form):
    ledger = forms.ModelChoiceField(queryset=Ledger.objects.all(),)
    description = forms.CharField(required=False)
    project = forms.ModelChoiceField(queryset=Project.objects.all(), required=False)
    cr = forms.DecimalField(decimal_places=2, required=False)
    dr = forms.DecimalField(decimal_places=2, required=False)
    # This init disallows empty formsets
    def __init__(self, *arg, **kwarg):
            super(LineItemForm, self).__init__(*arg, **kwarg)
            self.empty_permitted = False

我不知道 init 做了什么(arg、kwargs 和 super 对我来说仍然是个谜)。我从另一页复制了它。但它确实有效。

【讨论】:

  • 谢谢。重写 init 方法真的很有帮助。
【解决方案2】:

来源:Django documentation

ModelChoiceField 的默认值是 None,即使您指定了 queryset 属性。如果表格有效,对我来说这意味着None in Ledger.objects.all()True!你确定你的数据库中有Ledger 对象吗?

【讨论】:

    猜你喜欢
    • 2017-03-30
    • 1970-01-01
    • 2022-11-22
    • 2020-10-15
    • 2015-07-17
    • 2017-06-24
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    相关资源
    最近更新 更多