Как добавить атрибуты класса, идентификатора, заполнителя в поле в формах модели django

У меня есть модель django, как показано ниже

models.py

class Product(models.Model):
    name = models.CharField(max_length = 300)
    description = models.TextField(max_length = 2000)
    created = models.DateTimeField(auto_now_add = True)
    updated = models.DateTimeField(auto_now = True)

    def __unicode__(self):
        return self.name

forms.py

class ProductForm(ModelForm):
    class Meta:
        model = Product
        exclude = ('updated', 'created')

product_form.py (просто пример)

 <form enctype="multipart/form-data" action="{% url 'add_a_product' %}" method="post">
         <div id="name">
           {{form.name}}
         </div> 
         <div id="description">
           {{form.description}}
         </div> 
   </form> 

На самом деле я хочу отобразить/отобразить вывод html, как показано ниже.

<input id="common_id_for_inputfields" type="text" placeholder="Name" class="input-calss_name" name="Name">

<input id="common_id_for_inputfields" type="text" placeholder="Description" class="input-calss_name" name="description">

Итак, наконец, как добавить атрибуты (id, placeholder, class) в поля формы модели в приведенном выше коде?


person Shiva Krishna Bavandla    schedule 21.10.2013    source источник
comment
См. документацию для django.forms.Widget. атрибуты. Это реализовано в шаблон атрибутов.   -  person djvg    schedule 11.08.2020


Ответы (9)


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

#forms.py
class ProductForm(ModelForm):
    class Meta:
        model = Product
        exclude = ('updated', 'created')

    def __init__(self, *args, **kwargs):
        super(ProductForm, self).__init__(*args, **kwargs)
        self.fields['description'].widget = TextInput(attrs={
            'id': 'myCustomId',
            'class': 'myCustomClass',
            'name': 'myCustomName',
            'placeholder': 'myCustomPlaceholder'})
person Alex Parakhnevich    schedule 21.10.2013
comment
Это сработало для меня хорошо, за исключением того, что он стер все параметры из моего виджета «Выбрать». Я обнаружил, что вы можете полностью пропустить объявление виджета и по-прежнему устанавливать его атрибуты следующим образом: self.fields['description'].widget.attrs={ 'id': 'myCustomId', 'class': 'myCustomClass', 'name': 'myCustomName', 'placeholder': 'myCustomPlaceholder'} Также мне кажется, что это немного чище. - person bjesus; 14.10.2016
comment
Если вы хотите добавить классы начальной загрузки во все формы без необходимости каждый раз переопределять конструктор, см. мой ответ ниже. - person hurlbz; 27.01.2017
comment
Есть ли способ указать тот же идентификатор, что и имя? - person cwhisperer; 23.01.2019

Идентификаторы полей должны автоматически генерироваться django, чтобы переопределить другие поля:

class ProductForm(ModelForm):
    class Meta:
        model = Product
        exclude = ('updated', 'created')

    def __init__(self, *args, **kwargs):
        super(ProductForm, self).__init__(*args, **kwargs)
        self.fields['name'].widget.attrs\
            .update({
                'placeholder': 'Name',
                'class': 'input-calss_name'
            })
person mariodev    schedule 21.10.2013
comment
Действительно ли идентификатор ДОЛЖЕН генерироваться автоматически? Вы также можете переопределить идентификатор. - person Alex Parakhnevich; 21.10.2013
comment
Вы также можете переопределить id (точно так же, как я показал вам, вы можете переопределить любой атрибут), но я думаю, что лучше использовать сгенерированные django идентификаторы, если только вы не имеете над ними никакого контроля (например, когда вы используете сторонние js-библиотеки или что-л..) - person mariodev; 21.10.2013

Мне очень нравится ответ Дмитрия Синцова, но он не работает. Вот версия, которая работает:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    for field in iter(self.fields):
        self.fields[field].widget.attrs.update({
            'class': 'form-control'
    })

Обновить

добавьте это условие для лучшего

if self.fields[field].widget.__class__.__name__ in ('AdminTextInputWidget' , 'Textarea' , 'NumberInput' , 'AdminURLFieldWidget', 'Select'): 
     self.fields[field].widget.attrs.update({ 'class': 'form-control' })
person Derick Hayes    schedule 15.07.2015
comment
Это намного лучше, чем каждый раз формировать весь виджет. Я создал класс BasicForm, который расширяет forms.ModelForm, который делает это. Я просто расширяю BasicForm вместо формы модели и автоматически получаю классы начальной загрузки для всех форм. Я пошел еще дальше и добавил классы к любым пользовательским классам css, которые уже могут быть там. Смотрите мой ответ для примера кода. - person hurlbz; 27.01.2017

Вы можете обновить form.py, как показано ниже.

class ProductForm(ModelForm):
    class Meta:
        model = Product
        exclude = ('updated', 'created')
        widgets={
                   "name":forms.TextInput(attrs={'placeholder':'Name','name':'Name','id':'common_id_for_imputfields','class':'input-class_name'}),
                   "description":forms.TextInput(attrs={'placeholder':'description','name':'description','id':'common_id_for_imputfields','class':'input-class_name'}),
                }  
person kali sharma    schedule 17.01.2014

Слегка измененная версия отличного ответа mariodev, добавляющая класс начальной загрузки ко всем полям формы, поэтому мне не нужно заново создавать виджеты ввода формы для каждого поля вручную (короткий Python 3.x super()):

class ProductForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in self.fields:
            self.fields[field].widget.attrs.update({
                'class': 'form-control'
            })
person Dmitriy Sintsov    schedule 23.06.2015
comment
Это также работает, если вы используете self.fields вместо self.Meta.fields. - person j4n7; 09.05.2017

Добавление к ответу от Дерика Хейса. Я создал класс BasicForm, который расширяет forms.ModelForm, который добавляет классы начальной загрузки к каждой форме, которая его расширяет.

Для своих форм я просто расширяю BasicForm вместо формы модели и автоматически получаю классы начальной загрузки для всех форм. Я пошел еще дальше и добавил классы к любым пользовательским классам css, которые уже могут быть там.

class BaseModelForm(forms.ModelForm):

def __init__(self, *args, **kwargs):
    super(BaseModelForm, self).__init__(*args, **kwargs)
    # add common css classes to all widgets
    for field in iter(self.fields):
        #get current classes from Meta
        classes = self.fields[field].widget.attrs.get("class")
        if classes is not None:
            classes += " form-control"
        else:
            classes = "form-control"
        self.fields[field].widget.attrs.update({
            'class': classes
        })
person hurlbz    schedule 27.01.2017

Фильтр add_class для добавления класса CSS в поле формы:

 {% load widget_tweaks %}     
    <form enctype="multipart/form-data" action="{% url 'add_a_product' %}" method="post">
                 <div id="name">
                   {{form.name|add_class:"input-calss_name"}}
                 </div> 
                 <div id="description">
                   {{form.description|add_class:"input-calss_name"}}
                 </div> 
           </form> 

библиотека django-widget-tweaks

person Sunny Multani    schedule 27.10.2017
comment
Если вы не хотите переопределять формы по умолчанию, это путь! Я использую его в проектах Django уже много лет. {% render_field field class+="form-check-input" %} - person Jon; 31.07.2019

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

class ProductForm(ModelForm):
    name = forms.CharField(label='name ', 
            widget=forms.TextInput(attrs={'placeholder': 'name '}))
person Rafael Cabral    schedule 03.06.2015

Я знаю, что это старый вопрос, но если кто-то все еще хочет добавить пользовательский класс во все поля своей формы, вы можете использовать этот один лайнер

class ProductForm(ModelForm):
    class Meta:
        model = Product
        exclude = ('updated', 'created')
def __init__(self, *args, **kwargs):
    super(ProductForm, self).__init__(*args, **kwargs)
    custom_attrs = {
        'class': 'form-control',
        'toggle-data': 'mydiv',
    }
    # adds our custom_attrs to each element of the form 
    [self.fields[i].widget.attrs.update(custom_attrs) for i in self.fields]
person wetler    schedule 10.10.2020