Определить класс css в формах django

Предположим, у меня есть форма

class SampleClass(forms.Form):
    name = forms.CharField(max_length=30)
    age = forms.IntegerField()
    django_hacker = forms.BooleanField(required=False)

Есть ли способ определить классы css для каждого поля, чтобы затем я мог использовать jQuery на основе класса на моей отображаемой странице?

Я надеялся, что мне не придется вручную создавать форму.

вау, все проголосовали за это? docs.djangoproject.com/en/dev/ref/forms/widgets/…

Skylar Saveland 03.11.2010 22:10

@skyl Я бы воспринял это как указание на то, что его нелегко найти в документации django. Я просмотрел и выполнил несколько поисков в Google, но не смог найти этого, так что я рад за вопрос, и он получил мою поддержку.

Nils 31.05.2012 21:54

Я знаю, что это старый поток, но в полях формы Django теперь есть класс id_fieldname.

ratsimihah 05.08.2013 20:13

См. этот ответ о том, как определять классы для поля формы внутри шаблона, соблюдая существующие классы полей.

dimyG 13.12.2016 23:47
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
198
4
150 311
13
Перейти к ответу Данный вопрос помечен как решенный

Ответы 13

Ответ принят как подходящий

Ответил на свой вопрос. Вздох

http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.Widget.attrs

Я не понимал, что это было передано в конструктор виджетов.

Означает ли это, что его нельзя использовать с классом ModelForm?

xster 03.05.2011 06:32

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

Tom 12.05.2011 20:05

Вот еще одно решение для добавления определений классов к виджетам после объявления полей в классе.

def __init__(self, *args, **kwargs):
    super(SampleClass, self).__init__(*args, **kwargs)
    self.fields['name'].widget.attrs['class'] = 'my_class'

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

Daniel Naab 31.12.2008 01:37

Это предполагает, что вы хотите вводить данные для каждого поля в форме, что часто бывает не так. Форма не обязательно привязана к модели - она ​​может быть привязана ко многим моделям. В случае, если поля модели и поля формы имеют соотношение 1: 1, тогда да, ModelForm - гораздо лучший выбор.

ashchristopher 31.12.2008 07:29

Вот вариант вышеупомянутого, который предоставит всем полям один и тот же класс (например, jquery с красивыми закругленными углами).

  # Simple way to assign css class to every field
  def __init__(self, *args, **kwargs):
    super(TranslatedPageForm, self).__init__(*args, **kwargs)
    for myField in self.fields:
      self.fields[myField].widget.attrs['class'] = 'ui-state-default ui-corner-all'

Расширение метода, указанного на docs.djangoproject.com:

class MyForm(forms.Form): 
    comment = forms.CharField(
            widget=forms.TextInput(attrs = {'size':'40'}))

Я думал, что знать собственный тип виджета для каждого поля было проблематично, и считал забавным переопределить значение по умолчанию, просто поместив имя класса в поле формы. Мне кажется, это работает:

class MyForm(forms.Form): 
    #This instantiates the field w/ the default widget
    comment = forms.CharField()

    #We only override the part we care about
    comment.widget.attrs['size'] = '40'

Мне это кажется немного чище.

Это именно то, что другие говорили много лет назад, за исключением того, что вы делаете это с «размером», а не с «классом», как было запрошено.

Chris Morgan 25.11.2010 03:11

@Chris Morgan На самом деле, он первый предложил использовать comment.widget.attrs в самом объявлении формы (вместо того, чтобы возиться с в этом или делать это в представлении).

DarwinSurvivor 27.07.2012 03:14

Вот простой способ изменить вид. добавьте ниже перед тем, как передать его в шаблон.

form = MyForm(instance = instance.obj)
form.fields['email'].widget.attrs = {'class':'here_class_name'}

Еще одно решение, которое не требует изменений в коде Python и поэтому лучше подходит для дизайнеров и одноразовых изменений презентации: Джанго-виджет-настройки. Надеюсь, кому-нибудь это пригодится.

Надо сказать, разумное решение Только. Спасибо!. Код Python, и особенно определение формы, - это последнее место, куда можно поместить элементы для стилизации - они определенно относятся к шаблонам.

Boris Chervenkov 13.11.2011 03:09

Это отличная библиотека! Жаль, что этот ответ похоронен на дне.

Chris Lacasse 11.01.2012 19:35

Отлично! Для этого я разработал несколько фильтров, но этот проект намного мощнее. Спасибо!

msbrogli 08.06.2012 21:19

Это должен быть принятый ответ - гораздо лучший подход. Жаль, что это добавляет еще одну зависимость.

Erik 27.08.2012 06:10

похоже, что это не работает для шаблонов Jinjia2. Я бы так хотел, потому что это отличное решение. {{myform.email | safe | add_class ("css_class_1 css_class_2")}}

David Dehghan 28.02.2013 13:22

Да, это библиотека шаблонных тегов / фильтров для шаблонизатора django; Поддержка jinja2 потребует некоторой работы (запросы на вытягивание приветствуются).

Mikhail Korobov 28.02.2013 13:44

на самом деле это работает и для Jinja2 :-) Я изменил порядок безопасного файла и добавил круглые скобки вместо двоеточия {{myform.email | add_class ("css_class_1 css_class_2") | safe}} спасибо за то, что написали это. он должен быть частью Django.

David Dehghan 28.02.2013 14:07

вау :) Я думаю, вы используете какой-то пакет интеграции jinja2 для django?

Mikhail Korobov 28.02.2013 14:19

Даже разработчику кажется, что шаблоны - подходящее место для этого.

HorseloverFat 29.04.2014 17:13
django-widget-tweaks вроде не поддерживается. Есть ли альтернативы?
utapyngo 28.12.2017 19:58

django-widget-tweaks - это проект jazzband на год или около того, любой может помочь - присоединяйтесь к jazzband org, и у вас есть права на внесение изменений в django-widget-tweaks. jazzband org разрешено делать релизы на pypi. Так что если кто-то хочет помочь, я ему даже не нужна. Посмотрим, как это будет работать :) Похоже, что люди используют пакет и думают, что он хорош, но никто не предпринимает никаких шагов для его поддержки. Нужны сопровождающие. Пакет очень простой: менее 200 строк кода, из которых всего около 30 строк - основная логика. 90% + тестовое покрытие. Если вы сочтете это полезным, пожалуйста, помогите.

Mikhail Korobov 28.12.2017 21:57

Используйте Джанго-виджет-настройки, он прост в использовании и работает довольно хорошо.

В противном случае это можно сделать с помощью настраиваемого фильтра шаблона.

Учитывая, что вы визуализируете свою форму таким образом:

<form action = "/contact/" method = "post">
    {{ form.non_field_errors }}
    <div class = "fieldWrapper">
        {{ form.subject.errors }}
        <label for = "id_subject">Email subject:</label>
        {{ form.subject }}
    </div>
</form>

form.subject - это экземпляр BoundField, который имеет метод as_widget.

вы можете создать собственный фильтр «addcss» в «my_app / templatetags / myfilters.py»

from django import template

register = template.Library()

@register.filter(name='addcss')
def addcss(value, arg):
    css_classes = value.field.widget.attrs.get('class', '').split(' ')
    if css_classes and arg not in css_classes:
        css_classes = '%s %s' % (css_classes, arg)
    return value.as_widget(attrs = {'class': css_classes})

А затем примените свой фильтр:

{% load myfilters %}
<form action = "/contact/" method = "post">
    {{ form.non_field_errors }}
    <div class = "fieldWrapper">
        {{ form.subject.errors }}
        <label for = "id_subject">Email subject:</label>
        {{ form.subject|addcss:'MyClass' }}
    </div>
</form>

Затем form.subjects будет отображаться с помощью класса css "MyClass".

Надеюсь на эту помощь.

ИЗМЕНИТЬ 1

  • Обновить фильтр согласно ответу dimyG

  • Добавить ссылку django-widget-tweak

РЕДАКТИРОВАТЬ 2

  • Обновить фильтр согласно комментарию Bhyd

Это здорово! Это СУХОЙ, и он отделяет слой отображения от слоя управления. +1 от меня!

alekwisnia 20.11.2013 19:12

Однако сейчас я заметил один недостаток. Если я определяю класс в attrs виджета, то они переопределяются этим фильтром addcss. У вас есть идеи, как это объединить?

alekwisnia 21.11.2013 18:16

Я имею в виду, что as_widget () переопределяет attrs. Как убедиться, что он использует существующие атрибуты и расширяет их новыми?

alekwisnia 22.11.2013 20:08

См. этот ответ о том, как уважать существующие классы полей.

dimyG 13.12.2016 23:45
get('class', None).split(' ') завершится ошибкой, если тег нет имеет атрибут класса, поскольку возвращается None. Смена на get('class', '').split(' ') работает
dtasev 25.04.2018 00:41

@Bhyd, вы правы, спасибо, я отредактировал свой ответ.

Charlesthk 29.06.2018 09:52

Вы спасли мою жизнь! TY

Mike Boutin 05.10.2018 01:17

Если вы хотите, чтобы все поля в форме наследовали определенный класс, вы просто определяете родительский класс, который наследуется от forms.ModelForm, а затем наследуете от него.

class BaseForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(BaseForm, self).__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            field.widget.attrs['class'] = 'someClass'


class WhateverForm(BaseForm):
    class Meta:
        model = SomeModel

Это помогло мне автоматически добавить класс 'form-control' ко всем полям всех форм моего приложения без добавления репликации кода.

пожалуйста, начинайте имена классов с верхнего регистра (также, BaseForm кажется лучшим названием для этого)

Alvaro 05.02.2015 03:45

Оказывается, вы можете сделать это в конструкторе формы (функция в этом) или после того, как был инициирован класс формы. Иногда это требуется, если вы не пишете свою собственную форму и эта форма поступает откуда-то еще -

def some_view(request):
    add_css_to_fields = ['list','of','fields']
    if request.method == 'POST':
        form = SomeForm(request.POST)
        if form.is_valid():
            return HttpResponseRedirect('/thanks/')
    else:
        form = SomeForm()

    for key in form.fields.keys():
        if key in add_css_to_fields:
            field = form.fields[key]
            css_addition = 'css_addition '
            css = field.widget.attrs.get('class', '')
            field.widget.attrs['class'] = css_addition + css_classes

    return render(request, 'template_name.html', {'form': form})

Если вы хотите добавить класс в поле формы в шаблоне (не в view.py или form.py), например, в случаях, когда вы хотите изменить сторонние приложения, не переопределяя их представления, тогда фильтр шаблона, как описано в Charlesthkотвечать очень удобно. Но в этом ответе фильтр шаблона переопределяет любые существующие классы, которые может иметь поле.

Я попытался добавить это как правку, но было предложено написать новый ответ.

Итак, вот тег шаблона, который учитывает существующие классы поля:

from django import template

register = template.Library()


@register.filter(name='addclass')
def addclass(field, given_class):
    existing_classes = field.field.widget.attrs.get('class', None)
    if existing_classes:
        if existing_classes.find(given_class) == -1:
            # if the given class doesn't exist in the existing classes
            classes = existing_classes + ' ' + given_class
        else:
            classes = existing_classes
    else:
        classes = given_class
    return field.as_widget(attrs = {"class": classes})

Спасибо за ваше предложение. Я соответственно отредактировал свой ответ, используя более «питонический» подход.

Charlesthk 14.12.2016 02:01

отлично !! это то, что я искал

ugali soft 30.10.2017 19:49

Вы также можете использовать Django Crispy Forms, это отличный инструмент для определения форм, если вы хотите использовать какую-либо структуру CSS, такую ​​как Bootstrap или Foundation. И там легко указать классы для полей вашей формы.

Тогда ваш класс формы хотел бы это:

from django import forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Submit, Field
from crispy_forms.bootstrap import FormActions

class SampleClass(forms.Form):
    name = forms.CharField(max_length=30)
    age = forms.IntegerField()
    django_hacker = forms.BooleanField(required=False)

    helper = FormHelper()
    helper.form_class = 'your-form-class'
    helper.layout = Layout(
        Field('name', css_class='name-class'),
        Field('age', css_class='age-class'),
        Field('django_hacker', css-class='hacker-class'),
        FormActions(
            Submit('save_changes', 'Save changes'),
        )
    )

Просто добавьте классы в форму следующим образом.

class UserLoginForm(forms.Form):
    username = forms.CharField(widget=forms.TextInput(
        attrs = {
        'class':'form-control',
        'placeholder':'Username'
        }
    ))
    password = forms.CharField(widget=forms.PasswordInput(
        attrs = {
        'class':'form-control',
        'placeholder':'Password'
        }
    ))

Вы можете попробовать это ..

class SampleClass(forms.Form):
  name = forms.CharField(max_length=30)
  name.widget.attrs.update({'class': 'your-class'})
...

Вы можете увидеть больше информации в: Виджеты Django

Другие вопросы по теме