Настроить / удалить 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 ]

2 голосов
/ 12 января 2014

Я сегодня возился с этим и просто придумал трусливый взлом изящное решение:

# 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: Нет необходимости в понижении голосов, безвредные патчи обезьян всегда под рукой.

1 голос
/ 14 февраля 2014

Я НАШУ РЕШЕНИЕ !!

Но не для 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),
        }
0 голосов
/ 24 августа 2018

Это становится более сложным, когда - это внешние ключи и если вы хотите - отфильтруйте варианты по некоторым критериям . В этом случае, если вы установите empty_label, а затем переназначите варианты (вы можете применить фильтрацию и здесь), пустая метка будет пустой:

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
        self.fields['verb'].queryset=Verb.objects.all()

В принципе, первая строка под init может быть применена ко всем полям в форме с помощью цикла или встроенного цикла:

def __init__(self,user, *args, **kwargs):
    super(NewTicket, self).__init__(*args, **kwargs)
    for f in self.fields:
       self.fields[f].empty_label = None # or "Please Select" etc
0 голосов
/ 26 апреля 2018

Начиная с Django 1.7, вы можете настроить метку для пустого значения, добавив значение в список выбора в определении поля модели. Из документации по настройке Выбор полей :

Если не указано пустое значение = False установлено в поле вместе со значением по умолчанию, тогда в поле выбора будет отображаться метка, содержащая «---------». Чтобы переопределить это поведение, добавьте кортеж к вариантам, содержащим None; например (Нет, «Ваша строка для отображения»). В качестве альтернативы вы можете использовать пустую строку вместо None, если это имеет смысл - например, в CharField.

Я проверил документацию для различных версий Django и обнаружил, что это добавлено в Django 1.7 .

0 голосов
/ 14 февраля 2018

Здесь много хороших ответов, но я все еще не совсем удовлетворен реализациями. Я также немного разочарован тем, что выбор виджетов из разных источников (внешние ключи, выбор) приводит к разному поведению.

У меня есть дизайн, с которым я работаю, где в полях выбора всегда есть пустой параметр, и если они требуются, рядом с ними будет звездочка, а форма просто не будет проверена, если остались пустыми. Тем не менее, я могу корректно переопределить empty_label только для полей, которые не TypedChoiceField s.

Вот как будет выглядеть . Первым результатом всегда является имя поля - в моем случае, label.

select widget

Вот что я в итоге сделал. Ниже приведен переопределенный __init__ метод моей формы:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    for _, field in self.fields.items():
        if hasattr(field, 'empty_label'):
            field.empty_label = field.label
        if isinstance(field, forms.TypedChoiceField):
            field.choices = [('', field.label)] + [choice for choice in field.choices if choice[0]]
...