在 Django 上所需的 selectDateWidget 上显示 empty_label

Display empty_label on required selectDateWidget on Django

根据 Django 的 Doc on SelectDateWidget (https://docs.djangoproject.com/en/1.8/ref/forms/widgets/#selectdatewidget),如果不需要 DateField,将显示 empty_label。我注意到如果需要 DateField,小部件上的默认值将是 January1<current-year>。有没有办法使 DateField 成为必需,但在初始表单上显示带有 empty_label(例如 -----)的小部件?

不幸的是,SelectDateWidget 中的空标签仅在不需要字段时使用,但您可以通过子类化 SelectDateWidget 并覆盖 create_select 方法来简单地更改它:

class MySelectDateWidget(SelectDateWidget):

    def create_select(self, *args, **kwargs):
        old_state = self.is_required
        self.is_required = False
        result = super(MySelectDateWidget, self).create_select(*args, **kwargs)
        self.is_required = old_state
        return result

但在那种情况下,您可能还必须覆盖对您的字段的验证,因此它会抛出该字段是必需的错误,而不是当 select 保留为空白值时该选择无效。

查看 SelectDateWidget 的代码,没有很好的方法来做到这一点(django 2.1.4)。 我的解决方案是添加空选项 client-side(using jquery):

$(document).ready(function() {
  $('#select-widget-id select').each(function() {
    if(!$(this).children('[value=""], [selected]').length) {
      $(this).prepend('<option value="" selected="selected">---</option>');
    }
  });
});

虽然 create_select 已在最新版本的 Django 中删除,但我能够使用与@GwynBleidD 的答案非常相似的方法,方法是子类化 SelectDateWidget 并覆盖 get_context.

class MySelectDateWidget(SelectDateWidget):

    def get_context(self, name, value, attrs):
        old_state = self.is_required
        self.is_required = False
        context = super(MySelectDateWidget, self).get_context(name, value, attrs)
        self.is_required = old_state
        return context

另一种解决方法是将您的表单字段设置为可选(required=False)并实施自定义验证以确保该字段具有内容:

from django import forms

class MyForm(forms.ModelForm):

    myfield = forms.DateField(widget=forms.SelectDateWidget(empty_label=(u'year', u'month', u'day')),
                              required=False)

    def clean_myfield(self):
        value = self.cleaned_data['myfield']
        if not value:
            raise forms.ValidationError(u'Please fill out myfield')
        return value