How do I set default widget attributes for a Django ModelForm?

跟風遠走 提交于 2019-12-18 11:55:46

问题


I'd like to set the class attribute for the TextInput Widget to one value for all the fields in my form that use it without having to list them all in Meta: widgets = {.... Is this possible?

Thanks.


回答1:


You can override the constructor in order to modify all TextInput widgets:

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

can you override init with a decorator? also, there should be an if statement before the attrs.update() becuase I want to set a default rather than override what may already be there. – Kevin

Untested, but I guess you can just inherit from MyForm if you use this a lot.




回答2:


Create a new widget with your CSS class:

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

In your form use your new widget in all your fields:

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



回答3:


One thing I've done in the past is create a lambda function that returns the fields I use often:

from django import forms

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

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

I don't remember why exactly I opted to use a function to handle my situation, but I suspect that it had something to do with creating separate instances of the forms.TextInput object for each form field....




回答4:


You can use following:

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() 

Now, every time you want to use default attrs for some widget, you just need to create class that inherits from DefaultAttrForm or DefaultAttrModelForm and overwrite method get_default_attrs. Example for normal Django Form:

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

For Model form use following:

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



回答5:


For ModelForm we can use this.

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 


来源:https://stackoverflow.com/questions/3679431/how-do-i-set-default-widget-attributes-for-a-django-modelform

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!