Я выводил поля формы в шаблон, подобный этому {{ form.first_name }}
, и я хотел бы добавить к нему класс (например, blueprint span-x-class). Поэтому я хотел бы узнать, есть ли для этого приятное готовое решение (шаблонный фильтр), который я мог бы использовать в моде {{ form.first_name|add_class:"span-4" }}
? (Я просто хочу знать, если разработчики Django или кто-то подумал об этом, но без моего ведома, прежде чем делать это самостоятельно)
Django: добавление классов CSS при рендеринге полей формы в шаблоне
Ответ 1
Чтобы решить эту проблему, я создал свой собственный фильтр шаблонов, вы можете применить его к любому тегу, а не только к элементам ввода!
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
Ответ 2
Вам нужно только установить Django widget_tweaks
pip install django-widget-tweaks
После этого вы можете сделать что-то подобное в своем шаблоне:
{{ form.search_query|attr:"type:search" }}
-
Прочитайте все здесь.
Ответ 3
Несколько дополнительных заметок о том, как получить доступ к 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 %}
в начало файла. Если я хочу добавить класс 'delete' в поле, я бы сделал это
{{ myfield|add_class:'delete' }}
Ответ 4
Другой способ - использовать метод 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
и т.д.
Ответ 5
Я все еще изучаю Django, но не мог бы вы сделать что-то вроде этого -
from django import forms
class SomeForm(forms.Form):
f = forms.CharField(label='x',widget=forms.TextInput(attrs={'class':'name'}))
Я думаю, что нет необходимости делать это на уровне шаблона (или использовать фильтры), если у вас нет требования, которое я не понял.
Ответ 6
Еще одно замечание о решении lazerscience: если вы примените его к <select> элемент без атрибута класса, строка, замещающая в случае else, создаст что-то вроде этого:
<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="..." > , что логически корректно для любого элемента формы.
Ответ 7
Вам нужно явно указать виджет и добавить класс, используя attrs
аргумент ключевого слова. Другого пути я не знаю.
Однако, если это слишком громоздко, вы все равно можете просто поместить поле в другой элемент, например div или span, и добавить к нему класс. Затем соответствующим образом измените свой CSS.