自定义/删除Djangoselect框空白选项
我正在使用Django 1.0.2。 我写了一个由Model支持的ModelForm。 这个模型有一个ForeignKey,其中blank = False。 当Django为这个表单生成HTML时,它会为ForeignKey引用的表中的每一行创build一个select框。 它还会在列表顶部创build一个没有值的选项,并显示为一系列破折号:
<option value="">---------</option>
我想知道的是:
- 从select框中删除这个自动生成选项的最简洁的方法是什么?
-
什么是最简洁的方式来定制它,使其显示为:
<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:
-
删除空的选项(扩展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
-
自定义空白选项标签本质上是一样的:
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
这样的其他字段,您可以将default
为None
,但是这对于Django 1.11中的ForeignKey
字段不起作用。