Стилизация CSS в формах Django
Я хотел бы стилизовать следующее:
forms.py:
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea)
contact_form.html:
<form action="" method="post">
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
Например, как мне установить класс или идентификатор для subject
, email
, message
чтобы предоставить внешнюю таблицу стилей?
Ответы
Ответ 1
Взятый из моего ответа на:
Как пометить поля формы с < div class= 'field_type' > в Django
class MyForm(forms.Form):
myfield = forms.CharField(widget=forms.TextInput(attrs={'class' : 'myfieldclass'}))
или
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['myfield'].widget.attrs.update({'class' : 'myfieldclass'})
или
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
'myfield': forms.TextInput(attrs={'class': 'myfieldclass'}),
}
--- EDIT ---
Вышеизложенное является самым простым изменением, чтобы сделать исходный код вопроса, который выполняет задание. Это также заставляет вас не повторять себя, если вы повторно используете форму в других местах; ваши классы или другие атрибуты просто работают, если вы используете методы формы Django as_table/as_ul/as_p. Если вам нужен полный контроль для полностью персонализированного рендеринга, это четко документировано
- ИЗМЕНИТЬ 2 ---
Добавлен новый способ указания виджета и attrs для ModelForm.
Ответ 2
Это можно сделать с помощью пользовательского шаблона фильтра. Подумайте, как визуализировать вашу форму
<form action="/contact/" method="post">
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject }}
<span class="helptext">{{ form.subject.help_text }}</span>
</div>
</form>
form.subject
является экземпляром BoundField
который имеет метод as_widget()
.
Вы можете создать собственный фильтр addclass
в my_app/templatetags/myfilters.py:
from django import template
register = template.Library()
@register.filter(name='addclass')
def addclass(value, arg):
return value.as_widget(attrs={'class': arg})
И затем примените свой фильтр:
{% load myfilters %}
<form action="/contact/" method="post">
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject|addclass:'MyClass' }}
<span class="helptext">{{ form.subject.help_text }}</span>
</div>
</form>
form.subjects
будут отображаться с помощью класса MyClass
CSS.
Ответ 3
Если вы не хотите добавлять какой-либо код в форму (как указано в комментариях к @shadfc Answer), это, безусловно, возможно, вот два варианта.
Сначала вы просто ссылаетесь на поля отдельно в HTML, а не на всю форму сразу:
<form action="" method="post">
<ul class="contactList">
<li id="subject" class="contact">{{ form.subject }}</li>
<li id="email" class="contact">{{ form.email }}</li>
<li id="message" class="contact">{{ form.message }}</li>
</ul>
<input type="submit" value="Submit">
</form>
(Обратите внимание, что я также изменил его на несортированный список.)
Во-вторых, обратите внимание на документы вывод форм в формате HTML, Django:
Идентификатор поля, генерируется добавив 'id_' к имени поля. Идентификационные атрибуты и теги включается в выход по умолчанию.
Все поля формы уже имеют уникальный id. Таким образом, вы должны ссылаться на id_subject в вашем файле CSS, чтобы создать поле темы. Я должен отметить, так выглядит форма, когда вы берете HTML по умолчанию, который требует просто распечатать форму, а не отдельные поля:
<ul class="contactList">
{{ form }} # Will auto-generate HTML with id_subject, id_email, email_message
{{ form.as_ul }} # might also work, haven't tested
</ul>
См. предыдущую ссылку для других параметров при выводе форм (вы можете делать таблицы и т.д.).
Примечание. Я понимаю, что это не то же самое, что добавлять класс к каждому элементу (если вы добавили поле в форму, вам также нужно будет обновить CSS), но это достаточно просто, чтобы ссылаться на все полей по id в вашем CSS, например:
#id_subject, #id_email, #email_message
{color: red;}
Ответ 4
Вы можете сделать следующее:
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
subject.widget.attrs.update({'id' : 'your_id'})
Надеюсь, что это работает.
Игнас
Ответ 5
В this в блоге вы можете добавлять классы css в свои поля, используя настраиваемый фильтр шаблонов.
from django import template
register = template.Library()
@register.filter(name='addcss')
def addcss(field, css):
return field.as_widget(attrs={"class":css})
Поместите это в свою папку templatetags/папку, и теперь вы можете сделать
{{field|addcss:"form-control"}}
Ответ 6
Вы можете использовать эту библиотеку: https://pypi.python.org/pypi/django-widget-tweaks
Это позволяет сделать следующее:
{% load widget_tweaks %}
<!-- add 2 extra css classes to field element -->
{{ form.title|add_class:"css_class_1 css_class_2" }}
Ответ 7
Ты можешь сделать:
<form action="" method="post">
<table>
{% for field in form %}
<tr><td>{{field}}</td></tr>
{% endfor %}
</table>
<input type="submit" value="Submit">
</form>
Затем вы можете добавить классы /id, например, к тегу <td>
. Конечно, вы можете использовать любые другие теги, которые вы хотите. Установите флажок Работа с формами Django в качестве примера того, что доступно для каждого field
формы (например, {{field}}
просто выводит тег ввода, а не метку и т.д.).
Ответ 8
Не видел этого действительно...
https://docs.djangoproject.com/en/1.8/ref/forms/api/#more-granular-output
Более подробный вывод
Методы as_p(), as_ul() и as_table() - это просто ярлыки для ленивых разработчиков - это не единственный способ отображения объекта формы.
класс BoundField
Используется для отображения HTML или атрибутов доступа для одного поля экземпляра формы.
Метод str() ( unicode на Python 2) отображает HTML для этого поля.
Чтобы получить один BoundField, используйте синтаксис словарного поиска в форме, используя имя поля в качестве ключа:
>>> form = ContactForm()
>>> print(form['subject'])
<input id="id_subject" type="text" name="subject" maxlength="100" />
Чтобы получить все объекты BoundField, выполните итерацию формы:
>>> form = ContactForm()
>>> for boundfield in form: print(boundfield)
<input id="id_subject" type="text" name="subject" maxlength="100" />
<input type="text" name="message" id="id_message" />
<input type="email" name="sender" id="id_sender" />
<input type="checkbox" name="cc_myself" id="id_cc_myself" />
Результат, специфичный для поля, отличает настройку auto_id объекта формы:
>>> f = ContactForm(auto_id=False)
>>> print(f['message'])
<input type="text" name="message" />
>>> f = ContactForm(auto_id='id_%s')
>>> print(f['message'])
<input type="text" name="message" id="id_message" />
Ответ 9
Вам не нужно переопределять класс формы __init__
, потому что Django устанавливает атрибуты name
и id
в HTML input
s. У вас может быть такой CSS:
form input[name='subject'] {
font-size: xx-large;
}
Ответ 10
Одним из решений является использование JavaScript для добавления необходимых классов CSS после того, как страница будет готова. Например, стиль django формирует вывод с помощью классов начальной загрузки (jQuery используется для краткости):
<script type="text/javascript">
$(document).ready(function() {
$('#some_django_form_id').find("input[type='text'], select, textarea").each(function(index, element) {
$(element).addClass("form-control");
});
});
</script>
Это позволяет избежать уродства, связанного с детализацией стилей в вашей бизнес-логике.
Ответ 11
Существует очень простой в установке и отличный инструмент для Django, который я использую для стилизации, и его можно использовать для всех интерфейсных фреймворков, таких как Bootstrap, Materialize, Foundation и т.д. Это называется виджетами-настройками. Документация: Widget Tweaks
- Вы можете использовать его в общих представлениях Django
- Или с вашими собственными формами:
из форм импорта django
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea)
Вместо использования значения по умолчанию:
{{ form.as_p }} or {{ form.as_ul }}
Вы можете отредактировать его по-своему, используя атрибут render_field, который дает вам более html-способ стилизации, как в этом примере:
template.html
{% load widget_tweaks %}
<div class="container">
<div class="col-md-4">
{% render_field form.subject class+="form-control myCSSclass" placeholder="Enter your subject here" %}
</div>
<div class="col-md-4">
{% render_field form.email type="email" class+="myCSSclassX myCSSclass2" %}
</div>
<div class="col-md-4">
{% render_field form.message class+="myCSSclass" rows="4" cols="6" placeholder=form.message.label %}
</div>
</div>
Эта библиотека дает вам возможность хорошо отделить ваш интерфейс от вашего бэкэнда
Ответ 12
В Django 1.10 (возможно, и раньше) вы можете сделать это следующим образом.
Модель:
class Todo(models.Model):
todo_name = models.CharField(max_length=200)
todo_description = models.CharField(max_length=200, default="")
todo_created = models.DateTimeField('date created')
todo_completed = models.BooleanField(default=False)
def __str__(self):
return self.todo_name
форма:
class TodoUpdateForm(forms.ModelForm):
class Meta:
model = Todo
exclude = ('todo_created','todo_completed')
Шаблон:
<form action="" method="post">{% csrf_token %}
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.todo_name.errors }}
<label for="{{ form.name.id_for_label }}">Name:</label>
{{ form.todo_name }}
</div>
<div class="fieldWrapper">
{{ form.todo_description.errors }}
<label for="{{ form.todo_description.id_for_label }}">Description</label>
{{ form.todo_description }}
</div>
<input type="submit" value="Update" />
</form>
Ответ 13
Изменить: Другой (немного лучший) способ сделать то, что я предлагаю, ответ здесь: Django формы поля ввода
Все вышеперечисленные варианты потрясающие, просто подумал, что я добавлю этот, потому что он отличается.
Если вы хотите, чтобы в ваших формах использовались пользовательские стили, классы и т.д., Вы можете сделать HTML-ввод в свой шаблон, соответствующий полю вашей формы. Например, для CharField (виджетом по умолчанию является TextInput
), допустим, вы хотите ввод текста в виде начальной загрузки. Вы бы сделали что-то вроде этого:
<input type="text" class="form-control" name="form_field_name_here">
И пока вы вводите имя поля формы, совпадающее с атрибутом name
html (и виджет, вероятно, также должен соответствовать типу ввода), Django будет запускать все те же валидаторы в этом поле при запуске validate
или form.is_valid()
а также
Стилизация других вещей, таких как метки, сообщения об ошибках и текст справки, не требует много обходных путей, потому что вы можете сделать что-то вроде form.field.error.as_text
и form.field.error.as_text
их так, как вам form.field.error.as_text
. Фактические поля - те, которые требуют некоторого возни.
Я не знаю, является ли это лучшим способом или способом, который я бы порекомендовал, но это способ, и это может быть правильным для кого-то.
Здесь полезное пошаговое руководство по стилю форм, и оно включает в себя большинство ответов, перечисленных в SO (например, использование attr для виджетов и настройки виджетов). https://simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually.html
Ответ 14
я могу использовать Reactjs для этой цели? вместо стайлинга форм
Ответ 15
Стилизация экземпляров виджета
Если вы хотите, чтобы один экземпляр виджета отличался от другого, вам нужно будет указать дополнительные атрибуты в момент создания экземпляра объекта виджета и присвоения его полю формы (и, возможно, добавить некоторые правила в ваши CSS файлы).
https://docs.djangoproject.com/en/2.2/ref/forms/widgets/
Для этого вы используете аргумент Widget.attrs при создании виджета:
class CommentForm(forms.Form):
name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
url = forms.URLField()
comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))
Вы также можете изменить виджет в определении формы:
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField()
name.widget.attrs.update({'class': 'special'})
comment.widget.attrs.update(size='40')
Или, если поле не объявлено непосредственно в форме (например, поля формы модели), вы можете использовать атрибут Form.fields:
class CommentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update({'class': 'special'})
self.fields['comment'].widget.attrs.update(size='40')
Затем Django включит дополнительные атрибуты в визуализированный вывод:
>>> f = CommentForm(auto_id=False)
>>> f.as_table()
<tr><th>Name:</th><td><input type="text" name="name" class="special" required></td></tr>
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" size="40" required></td></tr>
Ответ 16
Напишите свою форму как:
class MyForm(forms.Form):
name = forms.CharField(widget=forms.TextInput(attr={'class':'name'}))
message = forms.CharField(widget=forms.Textarea(attr={'class':'message'}))
В вашем HTML-поле сделайте что-то вроде:
{% for field in form %}
<div class="row">
<label for="{{ field.name}}">{{ field.name }}</label>{{ field }}
</div>
{% endfor %}
Затем в вашем CSS напишите что-то вроде:
.name{
/* you already have this class so create it style form here */
}
.message{
/* you already have this class so create it style form here */
}
label[for='message']{
/* style for label */
}
Надеюсь, что этот ответ стоит попробовать! Обратите внимание, что вы должны написать свои представления для отображения HTML файла, который содержит форму.