Добавьте класс CSS к опции в WTForms SelectField

Может ли кто-нибудь сказать мне, как назначить класс css значениям choices. Я хотел бы изменить фон каждого варианта с небольшим изображением, так как я могу сделать это с помощью wtforms и css?

class RegisterForm(Form):
    username = TextField('username', [validators.Length(min=3, max=50), validators.Required()])
    img_url = SelectField('avatar', 
            choices=[('static/images/avatars/1.jpg', '1'), 
                ('static/images/avatars/2.jpg', '2'),
                ('static/images/avatars/3.jpg', '3'), 
                ('static/images/avatars/4.jpg', '4'),
                ('static/images/avatars/5.jpg', '5'), 
                ('static/images/avatars/6.jpg', '6'),
                ('static/images/avatars/7.jpg', '7'), 
                ('static/images/avatars/8.jpg', '8'),
                ('static/images/avatars/9.jpg', '9'), 
                ('static/images/avatars/10.jpg','10')])

person Max    schedule 11.04.2014    source источник


Ответы (2)


Если вы заглянете глубоко в недра WTForms, вы найдете класс виджетов с именем SelectField.

это метод, называемый построением строки html:

@classmethod
def render_option(cls, value, label, selected, **kwargs):
    options = dict(kwargs, value=value)
    if selected:
        options['selected'] = True
    return HTMLString('<option %s>%s</option>' % (html_params(**options), escape(text_type(label))))

это метод __call__, который вызывает функцию render_options, определенную выше.

def __call__(self, field, **kwargs):
    kwargs.setdefault('id', field.id)
    if self.multiple:
        kwargs['multiple'] = True
    html = ['<select %s>' % html_params(name=field.name, **kwargs)]
    for val, label, selected in field.iter_choices():
        html.append(self.render_option(val, label, selected))
    html.append('</select>')
    return HTMLString(''.join(html))

Вы не сможете добавить атрибут class, просто создав экземпляр SelectField. Когда вы делаете это, он неявно создает экземпляры Option. Во время рендеринга методы render_options этих неявных экземпляров вызываются только с аргументами val, selected и label.

Вы можете получить доступ к неявным экземплярам Option постфактум. Это не без проблем. Если вы посмотрите на пример @Johnston:

>>> i = 44
>>> form = F()
>>> for subchoice in form.a:
...     print subchoice(**{'data-id': i})
...     i += 1

Он делает именно это. Но вы должны предоставить атрибуты классу во время рендеринга. Вызов subchoice(**{'data-id': i}) фактически выдает ожидаемое HTML. Это создает серьезные проблемы, если вы интегрируете WTForms с механизмом шаблонов. Потому что что-то вроде jinja вызывает эти функции рендеринга для вас.

Если вам нужен такой тип поведения, я бы порекомендовал написать собственную реализацию SelectField, которая позволит вам передавать атрибуты в неявные экземпляры Option. Таким образом, механизм шаблонов может просто вызывать render, а вы можете сохранять свои определения формы в своих forms.py файлах.

person nsfyn55    schedule 01.05.2014

Я просто хотел, чтобы вы знали, что это возможно без патчей обезьяны или переписывания wtforms. Код библиотеки поддерживает это, хотя и не очень прямо. Я узнал об этом, потому что у меня была та же проблема, что и у вас, и я попытался написать исправление для WTForms и сам отправил PR, а потом узнал, что вы можете просто сделать это (я потратил дни, пытаясь понять это):

>>> from wtforms import SelectField, Form
>>> class F(Form):
...    a = SelectField(choices=[('a', 'Apple'), ('b', 'Banana')])
... 
>>> i = 44
>>> form = F()
>>> for subchoice in form.a:
...     print subchoice(**{'data-id': i})
...     i += 1
... 
<option data-id="44" value="a">Apple</option>
<option data-id="45" value="b">Banana</option>

Смотрите конво здесь:
https://github.com/wtforms/wtforms/pull/ 81

person Johnston    schedule 06.05.2014