为模型表单额外字段指定小部件(Django)

时间:2021-03-04 19:19:12

I have to add extra field to my model form. My approach is:

我必须在我的模型表单中添加额外的字段。我的方法是:

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'}),
        }

But it seems that widget definition for extra_field at class Meta is ignored, because i have a bare input tag instead of textarea on a template. So I apply next approach:

但似乎忽略了Meta类中extra_field的小部件定义,因为我在模板上有一个裸输入标记而不是textarea。所以我申请下一个方法:

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

It works perfectly for me, but I used to specify widgets for form fields at class Meta declaration. So I wonder:

它对我来说很完美,但我曾经在Meta类声明中为表单字段指定小部件。所以我想知道:

Why my first approach doesn't work? What I am doing wrong?

为什么我的第一种方法不起作用?我做错了什么?

2 个解决方案

#1


25  

It doesn't matter if it's an extra field. This works:

如果它是一个额外的字段并不重要。这有效:

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

This doesn't:

这不是:

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

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

This is not documented indeed, that's the best I could find in the docs that could relate to that behaviour (maybe it doesn't, it's just the best i could find):

这确实没有记录,这是我在文档中可以找到的最好的,可能与该行为有关(也许它没有,它只是我能找到的最好的):

If you explicitly instantiate a form field like this, Django assumes that you want to completely define its behavior [...] you must set the relevant arguments explicitly when declaring the form field.

如果您显式实例化这样的表单字段,Django假定您要完全定义其行为[...]您必须在声明表单字段时明确设置相关参数。

The implementation of this behaviour is in django/forms/models.py line 219:

此行为的实现位于django / forms / models.py第219行:

   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)

After line 206, fields['name'].widget is indeed the Textarea specified in Meta.widgets.

在第206行之后,fields ['name']。widget确实是Meta.widgets中指定的Textarea。

At line 219, fields is updated with declared_fields, and fields['name'].widget becomes django.forms.widgets.TextInput which is the default for CharField.

在第219行,字段使用declared_fields更新,而字段['name']。小部件变为django.forms.widgets.TextInput,这是CharField的默认值。

Apparently, explicit field definitions have priority.

显然,显式字段定义具有优先权。

Thanks for asking, good to know, great question.

谢谢你的提问,很高兴知道这个问题。

#2


2  

I solved the situation above with the following:

我用以下方法解决了上述情况:

class FooForm(forms.ModelForm):
    name = forms.CharField(widget=TextArea(attrs={'placeholder': u'Bla bla'}))
    class Meta:
        model = People

#1


25  

It doesn't matter if it's an extra field. This works:

如果它是一个额外的字段并不重要。这有效:

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

This doesn't:

这不是:

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

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

This is not documented indeed, that's the best I could find in the docs that could relate to that behaviour (maybe it doesn't, it's just the best i could find):

这确实没有记录,这是我在文档中可以找到的最好的,可能与该行为有关(也许它没有,它只是我能找到的最好的):

If you explicitly instantiate a form field like this, Django assumes that you want to completely define its behavior [...] you must set the relevant arguments explicitly when declaring the form field.

如果您显式实例化这样的表单字段,Django假定您要完全定义其行为[...]您必须在声明表单字段时明确设置相关参数。

The implementation of this behaviour is in django/forms/models.py line 219:

此行为的实现位于django / forms / models.py第219行:

   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)

After line 206, fields['name'].widget is indeed the Textarea specified in Meta.widgets.

在第206行之后,fields ['name']。widget确实是Meta.widgets中指定的Textarea。

At line 219, fields is updated with declared_fields, and fields['name'].widget becomes django.forms.widgets.TextInput which is the default for CharField.

在第219行,字段使用declared_fields更新,而字段['name']。小部件变为django.forms.widgets.TextInput,这是CharField的默认值。

Apparently, explicit field definitions have priority.

显然,显式字段定义具有优先权。

Thanks for asking, good to know, great question.

谢谢你的提问,很高兴知道这个问题。

#2


2  

I solved the situation above with the following:

我用以下方法解决了上述情况:

class FooForm(forms.ModelForm):
    name = forms.CharField(widget=TextArea(attrs={'placeholder': u'Bla bla'}))
    class Meta:
        model = People