Добавить класс для вывода Django label_tag () - PullRequest
27 голосов
/ 06 января 2009

Мне нужен какой-то способ добавить атрибут класса к выводу метода label_tag () для поля формы.

Я вижу, что есть возможность перейти в словарь attrs, и я проверил это в оболочке, и я могу сделать что-то вроде:

for field in form:
    print field.label_tag(attrs{'class':'Foo'})

Я увижу class = 'Foo' в своем выводе, но я не вижу способа добавить аргумент attrs из шаблона - на самом деле шаблоны разработаны специально для этого, нет?

Есть ли способ в моем определении формы определить класс, который будет отображаться в метке?

В форме я могу сделать следующее, чтобы дать входам класс

self.fields['some_field'].widget.attrs['class'] = 'Foo'

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

Ответы [ 7 ]

18 голосов
/ 20 июля 2012

Техника 1

Я не согласен с утверждением другого ответа о том, что фильтр будет "менее элегантным". Как видите, это действительно очень элегантно.

@register.filter(is_safe=True)
def label_with_classes(value, arg):

    return value.label_tag(attrs={'class': arg})

Использование этого в шаблоне также элегантно:

{{ form.my_field|label_with_classes:"class1 class2"}}

Техника 2

В качестве альтернативы, один из наиболее интересных методов, которые я нашел: Добавление * в обязательные поля .

Вы создаете декоратор для BoundField.label_tag, который будет вызывать его с attrs , установленными соответствующим образом. Затем вы делаете патч для BoundField, чтобы вызов BoundField.label_tag вызывал декорированную функцию.

from django.forms.forms import BoundField

def add_control_label(f):
    def control_label_tag(self, contents=None, attrs=None):
        if attrs is None: attrs = {}
        attrs['class'] = 'control-label'
        return f(self, contents, attrs) 
    return control_label_tag

BoundField.label_tag = add_control_label(BoundField.label_tag)    
11 голосов
/ 19 декабря 2009

Как насчет добавления класса CSS в поле формы в forms.py, например:

class MyForm(forms.Form):
    title = forms.CharField(widget=forms.TextInput(attrs={'class': 'foo'}))

тогда я просто делаю следующее в шаблоне:

<label for="id_{{form.title.name}}" class="bar">
    {{ form.title }}
</label>

Конечно, это можно легко изменить, чтобы работать внутри тега цикла for в шаблоне.

8 голосов
/ 06 января 2009

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

Если это задача очень важная; Я бы создал Mixin, который позволял бы мне аннотировать поля формы классами меток и предоставлять методы визуализации форм с использованием этих классов. Чтобы следующий код работал:

{{ form.as_table_with_label_classes }}

Но я бы хотел спросить; Вам действительно нужен класс на теге label? Я имею в виду HTML-дизайн. Это абсолютно необходимо добавить класс там? Разве это не может быть решено с помощью некоторых CSS, таких как:

encapsulating_selector label {
    some-attr: some-value;
}

Я иногда использую jQuery для таких случаев, где; улучшит страницу, если она будет работать, но не будет катастрофой, если не будет . И сохраняйте исходный HTML-код максимально простым.

2 голосов
/ 30 января 2015

Слишком поздно, но столкнулся с похожей проблемой. Надеюсь, это поможет вам.

class MyForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['myfield1'].widget.attrs.update(
            {'class': 'form-control'})
        self.fields['myfield2'].widget.attrs.update(
            {'class': 'form-control'})

    def as_two_col_layout(self):

        return self._html_output(
            normal_row='<div class="form-group"><span class="col-xs-2">%(label)s</span> <div class="col-xs-10">%(field)s%(help_text)s</div></div>',
            error_row='%s',
            row_ender='</div>',
            help_text_html=' <span class="helptext">%s</span>',
            errors_on_separate_row=True)

    class Meta:

        model = mymodel
        fields = ['myfield1', 'myfield2']
1 голос
/ 31 октября 2009

Я согласен с ответом номер один, с помощью css это можно сделать, но. Какой резон для этого в источнике django?

В django.forms.forms.py есть это определение, которое показывает, что есть код для отображения атрибутов в ярлыках:

class BoundField(StrAndUnicode): 
# ....
def label_tag(self, contents=None, attrs=None):
    contents = u'<label for="%s"%s>%s</label>' % (widget.id_for_label(id_), attrs, unicode(contents))

но _html_output вызывает эту функцию без атрибутов:

label = bf.label_tag(label) or ''

Так что, похоже, django частично подготовлен к этому, но на самом деле он не использовал его.

0 голосов
/ 30 августа 2013
class CustomBoundField(BoundField):
    def label_tag(self, contents=None, attrs=None):
        if self.field.required:
            attrs = {'class': 'required'}
        return super(CustomBoundField, self).label_tag(contents, attrs)

class ImportViewerForm(forms.Form):
    url = fields.URLField(widget=forms.TextInput(attrs={'class': 'vTextField'}))
    type = fields.ChoiceField(choices=[('o', 'Organisation'), ('p', 'Program')], widget=forms.RadioSelect,
                              help_text='Url contain infornation about this type')
    source = fields.ChoiceField(choices=[('h', 'hodex'), ('s', 'studyfinder')], initial='h', widget=forms.RadioSelect)

    def __getitem__(self, name):
        "Returns a BoundField with the given name."
        try:
            field = self.fields[name]
        except KeyError:
            raise KeyError('Key %r not found in Form' % name)
        return CustomBoundField(self, field, name)

class Media:
    css = {'all': [settings.STATIC_URL + 'admin/css/forms.css']}

Вам необходимо изменить метод label_tag в классе BoundField и использовать его в форме

0 голосов
/ 31 мая 2011
@register.simple_tag
def advanced_label_tag(field):
    """ Return form field label html marked to fill by `*` """
    classes = []
    attrs = {}
    contents = force_unicode(escape(field.label))

    if field.field.required:
        classes.append(u'required')
        contents = force_unicode('%s <span>*</span>'%escape(field.label))

    if classes:
        attrs['class'] = u' '.join(classes)

    return field.label_tag(contents=contents, attrs=attrs)
...