Указание виджета для дополнительного поля формы модели (Django)

Мне нужно добавить дополнительное поле в форму моей модели. Мой подход:

class MyForm(forms.ModelForm):
    extra_field = forms.CharField()
    class Meta:
        model = MyModel
        widgets = {
            #Does not work
            'extra_field': forms.Textarea(attrs={'placeholder': u'Bla bla'}),
        }

Но кажется, что определение виджета для extra_field в class Meta игнорируется, потому что у меня есть голый тег input вместо textarea в шаблоне. Поэтому я применяю следующий подход:

class MyForm(forms.ModelForm):
    #It works fine
    extra_field = forms.CharField(widget=forms.Textarea())
    class Meta:
        model = MyModel

У меня это прекрасно работает, но раньше я указывал виджеты для полей формы в объявлении class Meta. Поэтому мне интересно:

Почему мой первый подход не работает? Что я делаю неправильно?


person Sergey Goliney    schedule 23.08.2012    source источник
comment
Вы уверены, что используете Django 1.4? Form.Meta.widgets был представлен в Django 1.4.   -  person jpic    schedule 23.08.2012


Ответы (2)


Неважно, является ли это дополнительным полем. Это работает:

class FooForm(forms.ModelForm):
    class Meta:
        model = People
        widgets = { 
            'name': forms.Textarea(attrs={'placeholder': u'Bla bla'}),
        }   

Это не:

class FooForm(forms.ModelForm):
    name = forms.CharField()

    class Meta:
        model = People
        widgets = { 
            'name': forms.Textarea(attrs={'placeholder': u'Bla bla'}),
        }

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

Если вы явно создаете экземпляр поля формы, как это, Django предполагает, что вы хотите полностью определить его поведение [...] вы должны явно указать соответствующие аргументы при объявлении поля формы.

Реализация этого поведения находится в строке 219 django/forms/models.py:

   204         if opts.model:
   205             # If a model is defined, extract form fields from it.
   206             fields = fields_for_model(opts.model, opts.fields,
   207                                       opts.exclude, opts.widgets, formfield_callback)
   208             # make sure opts.fields doesn't specify an invalid field
   209             none_model_fields = [k for k, v in fields.iteritems() if not v]
   210             missing_fields = set(none_model_fields) - \
EE 211                              set(declared_fields.keys())
   212             if missing_fields:
   213                 message = 'Unknown field(s) (%s) specified for %s'
   214                 message = message % (', '.join(missing_fields),
   215                                      opts.model.__name__)
   216                 raise FieldError(message)
   217             # Override default model fields with any custom declared ones
   218             # (plus, include all the other declared fields).
   219             fields.update(declared_fields)

После строки 206 fields['name'].widget является действительно текстовой областью, указанной в Meta.widgets.

В строке 219 fields обновляется с помощью manifest_fields, а fields['name'].widget становится django.forms.widgets.TextInput, что является значением по умолчанию для CharField.

По-видимому, явные определения полей имеют приоритет.

Спасибо за вопрос, приятно знать, отличный вопрос.

person jpic    schedule 23.08.2012
comment
этот ответ не работает для меня. возможно джанго изменил поведение - person Marshall X; 14.07.2017
comment
Это все еще должно работать, возможно, задать еще один вопрос? - person jpic; 15.07.2017

Я решил описанную выше ситуацию следующим образом:

class FooForm(forms.ModelForm):
    name = forms.CharField(widget=TextArea(attrs={'placeholder': u'Bla bla'}))
    class Meta:
        model = People
person caneta    schedule 19.06.2013
comment
Добавляет ли это имя поля в таблицу? - person hlkstuv_23900; 13.11.2014