Настроить/удалить опцию выбора Django

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

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

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

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

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

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

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

Джефф

Изменить: я настроил поле ForeignKey как таковое:

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

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

Ответ 1

Не тестировал это, но на основе чтения кода 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

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

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

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

  class Meta:
    model = Thing

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

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

default = None - ответ: D

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

вы можете сделать это в admin:

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

Ответ 8

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:]

Ответ 9

Я сегодня возился с этим и только что придумал решение pust hack:

# 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, не пагубные патчи обезьяны всегда удобны.

Ответ 10

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

Ответ 11

Я нахожу РЕШЕНИЕ!!

Но не для ForeignKey: -)

Может быть, я могу вам помочь. Я посмотрел в исходном коде Django и обнаружил, что в django.forms.extras.widgets.SelecteDateWidget() - это свойство, называемое none_value, которое равно (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),
        }

Ответ 12

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

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

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