Настроить / удалить Django выбрать пустое поле - PullRequest
71 голосов
/ 11 апреля 2009

Я использую Django 1.0.2. Я написал ModelForm при поддержке Model. Эта модель имеет ForeignKey, где blank = False. Когда Django генерирует HTML для этой формы, он создает поле выбора с одним параметром для каждой строки в таблице, на которую ссылается ForeignKey. Он также создает параметр в верхней части списка, который не имеет значения и отображается в виде серии штрихов:

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

Я бы хотел знать:

  1. Какой самый чистый способ удалить эту автоматически сгенерированную опцию из поля выбора?
  2. Какой самый чистый способ настроить его так, чтобы он отображался как:

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

В поисках решения я наткнулся на Билет Django 4653 , что создало у меня впечатление, что у других был такой же вопрос, и что поведение Django по умолчанию могло быть изменено. Этому билету больше года, поэтому я надеялся, что для этого есть более чистый способ.

Спасибо за любую помощь,

Jeff

Редактировать: я настроил поле ForeignKey следующим образом:

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

Это устанавливает значение по умолчанию, так что оно больше не является параметром empty / dashes, но, к сожалению, оно не решает ни одного из моих вопросов. То есть опция пустого / тире все еще появляется в списке.

Ответы [ 15 ]

85 голосов
/ 11 апреля 2009

Не проверял это, но основываясь на чтении кода Джанго здесь и здесь Я считаю, что это должно работать:

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

РЕДАКТИРОВАТЬ : Это задокументировано , хотя вам не обязательно искать ModelChoiceField, если вы работаете с автоматически сгенерированной ModelForm.

РЕДАКТИРОВАТЬ : Как отмечает jlpp в своем ответе, это не завершено - вы должны переназначить выбор для виджетов после изменения атрибута empty_label. Поскольку это немного странно, другой вариант, который легче понять, это просто переопределить весь ModelChoiceField:

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

  class Meta:
    model = Thing
34 голосов
/ 11 апреля 2009

из документов

Пустой выбор не будет включен если поле модели имеет пустое значение = False и явное значение по умолчанию (по умолчанию значение будет изначально выбрано вместо этого).

поэтому установите значение по умолчанию, и все в порядке

22 голосов
/ 12 апреля 2009

С ответом Карла в качестве руководства и после того, как в течение нескольких часов копались вокруг источника Джанго, я думаю, что это полное решение:

  1. Чтобы удалить пустую опцию (расширяя пример Карла):

    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, но я не уверен. Я обнаружил, что когда эти поля инициализируются, их выбор передается виджету выбора (см. Django.forms.fields.ChoiceField._set_choices). Установка empty_label после инициализации не обновляет список вариантов выбора виджета. Я недостаточно знаком с Django, чтобы понять, следует ли это считать ошибкой.

19 голосов
/ 21 июля 2014

Вы можете использовать это на вашей модели:

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

по умолчанию = нет ответ: D

ПРИМЕЧАНИЕ: я пробовал это на Django 1.7

8 голосов
/ 30 июля 2012

Что касается django 1.4, все, что вам нужно, это установить значение «по умолчанию» и «blank = False» в поле выбора

class MyModel(models.Model):
    CHOICES = (
        (0, 'A'), 
        (1, 'B'),
    )
    choice_field = models.IntegerField(choices=CHOICES, blank=False, default=0)
5 голосов
/ 27 апреля 2013

вы можете сделать это в админке:

formfield_overrides = {
    models.ForeignKey: {'empty_label': None},
}
5 голосов
/ 01 сентября 2009

См. здесь для полного обсуждения и методов решения этого вопроса.

4 голосов
/ 24 мая 2015

self.fields['xxx'].empty_value = None не будет работать, если тип поля равен TypedChoiceField, для которого нет свойства 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

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:]
3 голосов
/ 21 сентября 2017

Для поля ForeignKey установка значения default на '' на модели приведет к удалению пустого параметра.

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

Для других полей, таких как CharField, вы можете установить default на None, но это не работает для полей ForeignKey в Django 1.11.

2 голосов
/ 27 марта 2015

Для последней версии 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)`
...