如何为Django ModelForm设置默认小部件属性?

时间:2010-09-09 18:26:01

标签: django django-forms

我想将TextInput Widget的class属性设置为我的表单中使用它的所有字段的一个值,而不必在Meta中列出它们:widgets = {....这可能吗?< / p>

感谢。

5 个答案:

答案 0 :(得分:14)

您可以覆盖构造函数以修改所有TextInput小部件:

from django import forms

class MyForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        for name, field in self.fields.items():
            if field.widget.__class__ == forms.widgets.TextInput:
                if 'class' in field.widget.attrs:
                    field.widget.attrs['class'] += ' my-class'
                else:
                    field.widget.attrs.update({'class':'my-class'})
    class Meta:
        model = MyModel
  

你可以用装饰器覆盖init吗?另外,在attrs.update()之前应该有一个if语句因为我想设置一个默认值而不是覆盖可能已存在的内容。 - 凯文

未经测试,但我猜你可以继承MyForm,如果你经常使用它。

答案 1 :(得分:3)

使用CSS类创建一个新小部件:

class PrettyWidget(forms.TextInput):
    class Media:
        css = {
            'all': ('pretty.css',)
        }

在您的表单中,在所有字段中使用新窗口小部件:

class ContactForm(forms.Form):
    subject = TextField(widget=PrettyWidget)

答案 2 :(得分:3)

我过去做过的一件事是创建一个lambda函数,它返回我经常使用的字段:

from django import forms

fancy = lambda: forms.TextInput(attrs={'class': 'derp'})

class MyForm(forms.Form):
    attr1 = fancy()
    attr2 = fancy()
    attr3 = fancy()

我不记得为什么我选择使用函数来处理我的情况,但我怀疑它与为每个表单字段创建forms.TextInput对象的单独实例有关....

答案 3 :(得分:1)

您可以使用以下内容:

def set_attrs_for_fields(fields, default_attrs):
    for field_name in fields:
        field = fields[field_name]

        try:
            default_widget_attr = default_attrs[field.widget.__class__]
            field.widget.attrs = default_widget_attr
        except KeyError:
            pass


class DefaultAttrForm(forms.Form):

    def __init__(self, *args, **kwargs):

        super(DefaultAttrForm, self).__init__(*args, **kwargs)

        set_attrs_for_fields(self.fields, self.get_default_attrs())


    def get_default_attrs(self):
        '''
        Child class should overwrite this method and return dict with example format

        {forms.TextInput: {'class': 'my_value'}}

        where keys, are widget classes for which default attrs will be set. 
        '''
        raise NotImplementedError()


class DefaultAttrModelForm(ModelForm):

    def __init__(self, *args, **kwargs):

        super(DefaultAttrModelForm, self).__init__(*args, **kwargs)

        set_attrs_for_fields(self.fields, self.get_default_attrs())


    def get_default_attrs(self):
        '''
        Child class should overwrite this method and return dict with example format

        {forms.TextInput: {'class': 'my_value'}}

        where keys, are widget classes for which default attrs will be set. 
        '''
        raise NotImplementedError() 

现在,每次要为某个窗口小部件使用默认attrs时,只需要创建继承自DefaultAttrForm或DefaultAttrModelForm并覆盖方法get_default_attrs的类。正常Django表单的示例:

class MyForm(DefaultAttrForm):
    my_field1 = forms.CharField(widget=forms.TextInput())
    my_field2 = forms.CharField(widget=forms.PasswordInput(attrs={'my_non_default': 'Non default'}))

    def get_default_attrs(self):
        # all fields with widget TextInput will have 
        # default attrs set to {'class': 'my_value'}

        return {forms.TextInput: {'class': 'my_value'},
               }


In [1]: form = MyForm()

In [2]: form.fields['my_field1'].widget.attrs
Out[2]: {'class': 'my_value'}

In [3]: form.fields['my_field2'].widget.attrs
Out[3]: {'my_non_default': 'Non default'}

对于模型表单,请使用以下命令:

class MyModelForm(DefaultAttrModelForm):

    class Meta:
        model = my_model

    def get_default_attrs(self):
        # all fields with widget TextInput will have 
        # default attrs set to {'class': 'my_value'}

        return {forms.TextInput: {'class': 'my_value'},
               }


In [1]: form = MyModelForm()

In [2]: form.fields['my_field1'].widget.attrs
Out[2]: {'class': 'my_value'}

In [3]: form.fields['my_field2'].widget.attrs
Out[3]: {'my_non_default': 'Non default'}

答案 4 :(得分:1)

对于ModelForm,我们可以使用它。

from django import forms
from django.contrib.auth.models import User 

class UserForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(UserForm, self).__init__(*args, **kwargs)

        # change a widget attribute:
        self.fields['user_permissions'].widget.attrs["size"] = 5
        self.fields['user_permissions'].widget.attrs["class"] = 'form-control required'

    class Meta:
        model = User