Как мне установить атрибуты виджета по умолчанию для Django ModelForm? - PullRequest
10 голосов
/ 09 сентября 2010

Я бы хотел установить атрибут класса для виджета TextInput равным одному значению для всех полей в моей форме, которые его используют, без необходимости перечислять их все в Meta: widgets = {.... Возможно ли это?

Спасибо.

Ответы [ 5 ]

14 голосов
/ 27 сентября 2010

Вы можете переопределить конструктор, чтобы изменить все виджеты 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, если вы используете это много.

3 голосов
/ 22 сентября 2010

Одна вещь, которую я делал в прошлом, это создание лямбда-функции, которая возвращает поля, которые я часто использую:

from django import forms

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

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

Я не помню, почему именно я решил использовать функцию для обработки своихситуация, но я подозреваю, что это как-то связано с созданием отдельных экземпляров объекта forms.TextInput для каждого поля формы ....

3 голосов
/ 20 сентября 2010

Создайте новый виджет с вашим классом CSS:

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

В вашей форме используйте новый виджет во всех ваших полях:

class ContactForm(forms.Form):
    subject = TextField(widget=PrettyWidget)
1 голос
/ 02 мая 2017

Для 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 
1 голос
/ 26 сентября 2010

Вы можете использовать следующее:

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

Теперь, каждый раз, когда вы хотите использовать атрибуты по умолчанию для некоторого виджета, вам просто нужно создать класс, который наследуется от 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'}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...