自定义/删除Djangoselect框空白选项

我正在使用Django 1.0.2。 我写了一个由Model支持的ModelForm。 这个模型有一个ForeignKey,其中blank = False。 当Django为这个表单生成HTML时,它会为ForeignKey引用的表中的每一行创build一个select框。 它还会在列表顶部创build一个没有值的选项,并显示为一系列破折号:

<option value="">---------</option> 

我想知道的是:

  1. 从select框中删除这个自动生成选项的最简洁的方法是什么?
  2. 什么是最简洁的方式来定制它,使其显示为:

     <option value="">Select Item</option> 

在寻找解决scheme时,我遇到了Django票据4653 ,这给我的印象是,其他人有同样的问题,Django的默认行为可能已被修改。 这张票已经一年多了,所以我希望有一个更清洁的方式来完成这些事情。

谢谢你的帮助,

杰夫

编辑:我已经这样configurationForeignKey字段:

 verb = models.ForeignKey(Verb, blank=False, default=get_default_verb) 

这确实设置了默认值,以便它不再是空的/破折号选项,但不幸的是,它似乎并没有解决我的任何一个问题。 也就是说,空/破折号选项仍然出现在列表中。

没有testing过这个,但基于阅读Django的代码在这里和这里我相信它应该工作:

 class ThingForm(models.ModelForm): class Meta: model = Thing def __init__(self, *args, **kwargs): super(ThingForm, self).__init__(*args, **kwargs) self.fields['verb'].empty_label = None 

编辑 :这是logging ,虽然你不一定知道寻找ModelChoiceField,如果您正在使用自动生成ModelForm。

编辑 :正如jlpp在他的答案中注意到,这是不完整的 – 你必须重新分配选项后,更改empty_label属性的小部件。 由于这有点不好意思,另一个可能更容易理解的选项只是覆盖整个ModelChoiceField:

 class ThingForm(models.ModelForm): verb = ModelChoiceField(Verb.objects.all(), empty_label=None) class Meta: model = Thing 

从文档

如果模型字段为空= False,并且显式默认值(将初始select默认值),则不会包含空白选项。

所以设置默认,你没事

以卡尔的回答为指导,在Django源代码周围扎根几个小时后,我认为这是一个完整的解决scheme:

  1. 删除空的选项(扩展Carl的例子):

     class ThingForm(models.ModelForm): class Meta: model = Thing def __init__(self, *args, **kwargs): super(ThingForm, self).__init__(*args, **kwargs) self.fields['verb'].empty_label = None # following line needed to refresh widget copy of choice list self.fields['verb'].widget.choices = self.fields['verb'].choices 
  2. 自定义空白选项标签本质上是一样的:

     class ThingForm(models.ModelForm): class Meta: model = Thing def __init__(self, *args, **kwargs): super(ThingForm, self).__init__(*args, **kwargs) self.fields['verb'].empty_label = "Select a Verb" # following line needed to refresh widget copy of choice list self.fields['verb'].widget.choices = self.fields['verb'].choices 

我认为这种方法适用于ModelChoiceFields呈现为HTML的所有场景,但我并不积极。 我发现当这些字段被初始化时,他们的select被传递给Select小部件(参见django.forms.fields.ChoiceField._set_choices)。 在初始化之后设置empty_label不会刷新Select小部件的选项列表。 我对Django不够熟悉,不知道这是否应该被视为一个错误。

你可以在你的模型上使用它:

 class MyModel(models.Model): name = CharField('fieldname', max_length=10, default=None) 

默认=无是答案:D

注:我试图在Django 1.7上

至于Django 1.4,所有你需要的是在选项字段上设置“默认”值和“空白=假”

 class MyModel(models.Model): CHOICES = ( (0, 'A'), (1, 'B'), ) choice_field = models.IntegerField(choices=CHOICES, blank=False, default=0) 

关于这个问题的完整讨论和解决方法,请看这里 。

你可以在admin中做到这一点:

 formfield_overrides = { models.ForeignKey: {'empty_label': None}, } 

self.fields['xxx'].empty_value = None将不起作用如果字段types是TypedChoiceField ,它没有empty_label属性。

我们应该做的是消除第一select:

1。 如果你想构build一个BaseForm自动检测TypedChoiceField

 class BaseForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(BaseForm, self).__init__(*args, **kwargs) for field_name in self.fields: field = self.fields.get(field_name) if field and isinstance(field , forms.TypedChoiceField): field.choices = field.choices[1:] # code to process other Field # .... class AddClientForm(BaseForm): pass 

2.只有几个表格,你可以使用:

 class AddClientForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(AddClientForm, self).__init__(*args, **kwargs) self.fields['xxx'].choices = self.fields['xxx'].choices[1:] 

今天我正在搞这个,刚刚想出了一个懦夫狡猾的解决scheme:

 # Cowardly handle ModelChoiceField empty label # we all hate that '-----' thing class ModelChoiceField_init_hack(object): @property def empty_label(self): return self._empty_label @empty_label.setter def empty_label(self, value): self._empty_label = value if value and value.startswith('-'): self._empty_label = 'Select an option' ModelChoiceField.__bases__ += (ModelChoiceField_init_hack,) 

现在你可以调整默认的ModelChoiceField空标签到任何你想要的东西。 🙂

PS:不需要downvotes,无害的猴子补丁总是方便。

对于最新版本的django,第一个答案应该是这样的

 class ThingForm(models.ModelForm): class Meta: model = Thing def __init__(self, *args, **kwargs): self.base_fields['cargo'].empty_label = None super(ThingForm, self).__init__(*args, **kwargs)` 

我find解决scheme!

但不是ForeignKey 🙂

也许我可以帮助你。 我查看了Django的源代码,发现在django.forms.extras.widgets.SelecteDateWidget()是一个名为none_value的属性equals(0,'—–'),所以我在我的代码中做了这个

 class StudentForm(ModelForm): class Meta: this_year = int(datetime.datetime.today().strftime('%Y')) birth_years = [] years = [] for year in range(this_year - 2, this_year + 3 ): years.append(year) for year in range(this_year - 60, this_year+2): birth_years.append(year) model = Student exclude = ['user', 'fullname'] date_widget = SelectDateWidget(years=years) date_widget.__setattr__('none_value', (0, 'THERE WAS THAT "-----" NO THERES THIS:-)')) widgets = { 'beginning': date_widget, 'birth': SelectDateWidget(years=birth_years), } 

对于ForeignKey字段,在模型上将default值设置为''将删除空白选项。

 verb = models.ForeignKey(Verb, on_delete=models.CASCADE, default='') 

对于像CharField这样的其他字段,您可以将defaultNone ,但是这对于Django 1.11中的ForeignKey字段不起作用。