自定义/删除Django选择框空白选项

jlp*_*lpp 73 python django django-models django-forms

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

<option value="">---------</option>
Run Code Online (Sandbox Code Playgroud)

我想知道的是:

  1. 从选择框中删除此自动生成选项的最简洁方法是什么?
  2. 定制它的最简洁方法是什么,以便它显示为:

    <option value="">Select Item</option>
    
    Run Code Online (Sandbox Code Playgroud)

在寻找解决方案时,我遇到了Django票4653,这给我的印象是其他人有同样的问题,并且Django的默认行为可能已被修改.这张票超过一年,所以我希望可能有更清洁的方法来完成这些事情.

谢谢你的帮助,

杰夫

编辑:我已经配置了ForeignKey字段:

verb = models.ForeignKey(Verb, blank=False, default=get_default_verb)
Run Code Online (Sandbox Code Playgroud)

这确实设置了默认值,因此它不再是空/短划线选项,但不幸的是它似乎无法解决我的任何问题.也就是说,空/破折号选项仍然出现在列表中.

Car*_*yer 87

没有测试,但基于阅读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
Run Code Online (Sandbox Code Playgroud)

编辑:这是记录的,但如果你正在使用自动生成的ModelForm,你不一定知道寻找ModelChoiceField.

编辑:正如jlpp在他的回答中所说,这是不完整的 - 你必须在更改empty_label属性后重新将选项分配给小部件.由于这有点hacky,可能更容易理解的另一个选项是覆盖整个ModelChoiceField:

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

  class Meta:
    model = Thing
Run Code Online (Sandbox Code Playgroud)


zal*_*lew 35

来自文档

如果模型字段为空白= False且显式默认值(最初将选择默认值),则不会包括空白选项.

所以设置默认值就可以了

  • 对ForeignKey字段执行此操作可能很危险.它可能*它的工作是CharField有选择.问题是ForeignKey没有完善的默认值. (3认同)

jlp*_*lpp 22

以Carl的回答为指导,在Django源码周围生根几个小时后,我认为这是完整的解决方案:

  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
    
    Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)

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

  • 这很奇怪,但我只是在我的应用程序上测试了这个,我不需要重置字段来删除空标签... (2认同)

Lu.*_*mec 19

您可以在模型上使用它:

class MyModel(models.Model):
    name = CharField('fieldname', max_length=10, default=None)
Run Code Online (Sandbox Code Playgroud)

默认=无答案:D

注意:我在Django 1.7上试过这个

  • 优秀。如[this link](https://docs.djangoproject.com/en/1.7/ref/models/fields/#choices)所述,模型字段中有“ blank = False”和任何“ default”值都将* *不**提供空白选项。 (2认同)

ykh*_*lev 8

至于django 1.4你需要的是在选择字段上设置"默认"值和"空白=假"

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


小智 5

请参阅此处,了解有关问题的完整辩论和解决方法.


小智 5

你可以在管理员中这样做:

formfield_overrides = {
    models.ForeignKey: {'empty_label': None},
}
Run Code Online (Sandbox Code Playgroud)


Mit*_*ril 5

self.fields['xxx'].empty_value = NoneTypedChoiceField如果您的字段类型没有属性,则不起作用empty_label

我们应该做的是删除第一个选择:

1. 如果你想构建一个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
Run Code Online (Sandbox Code Playgroud)

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:]
Run Code Online (Sandbox Code Playgroud)