Подтвердить что ты не робот

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

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

4b9b3361

Ответ 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.