it-roy-ru.com

Django: добавление классов CSS при рендеринге полей формы в шаблоне

Я выводю поля формы в шаблон, как этот {{ form.first_name }}, и я хотел бы добавить к нему класс (например, blueprint's span-x - class). Поэтому я хотел бы знать, есть ли готовое решение Nice (шаблонный фильтр) для этого, которое я мог бы использовать в виде {{ form.first_name|add_class:"span-4" }}? (Я просто хочу знать, думали ли разработчики Django или кто-либо еще об этом без моего ведома, прежде чем делать это самостоятельно)

32
Bernhard Vallant

Чтобы решить эту проблему, я сделал свой собственный шаблонный фильтр, вы можете применить его к любому тегу, а не только к элементам ввода!

class_re = re.compile(r'(?<=class=["\'])(.*)(?=["\'])')
@register.filter
def add_class(value, css_class):
    string = unicode(value)
    match = class_re.search(string)
    if match:
        m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class, 
                                                    css_class, css_class), 
                                                    match.group(1))
        print match.group(1)
        if not m:
            return mark_safe(class_re.sub(match.group(1) + " " + css_class, 
                                          string))
    else:
        return mark_safe(string.replace('>', ' class="%s">' % css_class))
    return value
22
Bernhard Vallant

Вам нужно только установить Django widget_tweaks

pip install Django-widget-tweaks

После этого вы можете сделать что-то подобное в своем шаблоне:

{{ form.search_query|attr:"type:search" }}

-

Прочитайте все об этом здесь .

46
Cristian Rojas

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

import re
from Django.utils.safestring import mark_safe
from Django import template
register = template.Library()

class_re = re.compile(r'(?<=class=["\'])(.*)(?=["\'])')
@register.filter
def add_class(value, css_class):
    string = unicode(value)
    match = class_re.search(string)
    if match:
        m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class, 
                                                    css_class, css_class), 
                                                    match.group(1))
        print match.group(1)
        if not m:
            return mark_safe(class_re.sub(match.group(1) + " " + css_class, 
                                          string))
    else:
        return mark_safe(string.replace('>', ' class="%s">' % css_class))
    return value

Я вставил это в файл с именем add_class.py. Структура каталогов: Mydjangoproject> general_tools_app> templatetags> add_class.py

general_tools_app - это приложение, которое собирает полезную функциональность, подобную этой, которую я добавляю в новые проекты Django.

(В каталогах general_tools_app и templatetags есть пустой файл __init__.py, чтобы они были правильно зарегистрированы)

В settings.py мой кортеж INSTALLED_APPS содержит запись mydjangoproject.general_tools_app.

Чтобы использовать фильтр в шаблоне, я добавляю строку {% load add_class %} вверху файла. Если я хочу добавить класс «удалить» в поле, я бы сделал это 

{{ myfield|add_class:'delete' }}
12
bitbutter

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

Определить пользовательский шаблон фильтра :

@register.filter
def add_class(field, class_name):
    return field.as_widget(attrs={
        "class": " ".join((field.css_classes(), class_name))
    })

И в вашем шаблоне:

{{ form.first_name|add_class:"span-4" }}

Вы также можете использовать as_widget для добавления других атрибутов, таких как placeholder и т.д.

10
user85461

Я все еще учу Джанго, но не мог бы ты сделать это как-то так -

from Django import forms

class SomeForm(forms.Form):
    f = forms.CharField(label='x',widget=forms.TextInput(attrs={'class':'name'}))

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

5
Srikar Appalaraju

Еще одно замечание о решении lazerscience: если вы примените это к элементу <select> без атрибута класса, замена строки в другом случае приведет к чему-то вроде этого:

<select name="state" id="id_state" class="class1 class2">
    <option value="AL" class="class1 class2">Alabama</option class="class1 class2">
    <option value="AK" class="class1 class2">Alaska</option class="class1 class2">
    <option value="AZ" class="class1 class2">Arizona</option class="class1 class2">
</select class="class1 class2">

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

return mark_safe(string.replace('>', ' class="%s">' % css_class, 1))

Этот последний аргумент (1) гарантирует, что только первый экземпляр ">" будет заменен на "class =" ... ">, что логически правильно для любого элемента формы.

3
Gavin

Вам нужно явно указать виджет и добавить класс с помощью ключевого аргумента attrs . Нет другого способа, о котором я знаю.

Однако, если это слишком громоздко, вы все равно можете просто обернуть поле в другой элемент, например, div или span, и добавить к нему класс. Затем измените свой CSS соответственно.

0
Deniz Dogan