【问题标题】:Django formset fails date validation with valid dateDjango formset 使用有效日期失败日期验证
【发布时间】:2018-08-29 15:06:02
【问题描述】:

我在使用 django 表单集时遇到了日期验证错误。当我formset.is_valid() 时,我没有收到相同的验证错误。我遇到的问题是is_valid 表单检查失败,仅在使用“2018 年 3 月 20 日”形式的日期时使用视图和模板(不在 shell 中),而它始终以“2018 年”通过-03-20”。

我还可以验证数据是否在 request.POST 中,但是当我在表单的 clean 方法中查找时 self.cleaned_data 中缺少无效的 due_date 键。考虑到无效的密钥,这可能是正常的,但我希望它发生在 干净之后,而不是之前,如果有的话。感觉可能是 django 错误,我使用的是 django 2.0.2

这里是构造的总结,它很普通:

# models.py
class Schedule(models.Model):
    # ...
    name = models.CharField(max_length=256)
    status = models.CharField(max_length=16, default=choices.NOT_STARTED, choices=choices.SCHEDULE_STATUSES)
    due_date = models.DateField(blank=True, null=True)
    # ...

# forms.py
class ScheduleForm(forms.ModelForm):

    class Meta:
        model = models.Schedule
        fields = ['name', 'user', 'status', 'due_date']

# views.py
def line_schedules_edit(request, line_slug):
    line = get_object_or_404(models.Line, slug=line_slug)
    queryset = line.schedules.all()

    ScheduleFormSet = modelformset_factory(models.Schedule, form=forms.ScheduleForm)

    if request.method == 'POST':
        schedules_formset = ScheduleFormSet(request.POST)

        if schedules_formset.is_valid():
            schedules_formset.save()
            return HttpResponseRedirect(reverse('products:line-schedules-edit',
                                                kwargs={'line_slug': line_slug}))
    else:
        schedules_formset = ScheduleFormSet(queryset=queryset)

    context = {
        'line': line,
        'formset': schedules_formset
    }

    return render(request, 'line-schedules-edit.html', context)


# template
{{ formset.management_form }}
{% csrf_token %}
{% for form in formset.forms %}
  {% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %}
  {% for field in form.visible_fields %}
    {{ field.errors }}
    {{ field }}
  {% endfor %}
{% endfor %}

使用这种结构,当我使用“2018 年 3 月 3 日”时,我不断收到到期日期无效的错误,而如果我在浏览器中提供“2018-03-18”的表单输入,它可以工作。然而,在 shell 中,我能够验证 两种 日期格式是否有效:

In [35]: POST = {
   'form-TOTAL_FORMS': '2',
   'form-INITIAL_FORMS': '0',
   'form-MAX_NUM_FORMS': '2',
   'form-0-name': 'Test',
   'form-0-status': 'Not started',
   'form-0-due_date': '2018-03-20',
   'form-1-name': 'Test',
   'form-1-status': 'Not started',
   'form-1-due_date': 'March 20, 2018'
}

In [36]: qdict = QueryDict('', mutable=True)
         qdict.update(POST)
         formset = ScheduleFormSet(qdict)

In [37]: formset.is_valid()
Out[37]: True

为什么视图和模板验证失败,为什么表单的 clean 方法中缺少 due_date 键?

【问题讨论】:

  • re:数据的时序和clean方法,Form.clean在特定字段验证运行后运行,如果此时认为字段值无效,则将其删除来自cleaned_data。在流程的后期,当您点击 clean 方法时,它不会出现。不过,我不知道为什么它没有通过验证。

标签: django django-forms django-2.0


【解决方案1】:

事实证明,我需要做的就是提供输入格式,以便在将格式发送到模型之前对其进行预处理。它一定是内置模型验证失败,因为它无法以“2018 年 3 月 2 日”的形式存储。

在表单中使用input_formats,我们可以在模型处理之前将其转换为所需的格式:

class ScheduleForm(forms.ModelForm):

    class Meta:
        model = models.Schedule
        fields = ['name', 'user', 'status', 'due_date']

    due_date = forms.DateField(widget=forms.DateInput(format='%d %B, %Y'),
                               input_formats=('%d %B, %Y',),
                               required=False)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-19
    相关资源
    最近更新 更多