在django Forms中定义css类

假设我有一张表格

class SampleClass(forms.Form):
name = forms.CharField(max_length=30)
age = forms.IntegerField()
django_hacker = forms.BooleanField(required=False)

是否有一种方法为我定义css类在每个字段,这样我就可以使用jQuery基于类在我渲染的页面?

我希望不必手动构建表单。

162792 次浏览

回答我自己的问题。叹息

http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.Widget.attrs

我没有意识到它被传递到小部件构造函数中。

下面是在类中声明字段后向小部件添加类定义的另一种解决方案。

def __init__(self, *args, **kwargs):
super(SampleClass, self).__init__(*args, **kwargs)
self.fields['name'].widget.attrs['class'] = 'my_class'

下面是上面的一个变种,它将给所有字段相同的类(例如jquery漂亮的圆角)。

  # Simple way to assign css class to every field
def __init__(self, *args, **kwargs):
super(TranslatedPageForm, self).__init__(*args, **kwargs)
for myField in self.fields:
self.fields[myField].widget.attrs['class'] = 'ui-state-default ui-corner-all'

扩展docs.djangoproject.com中指出的方法:

class MyForm(forms.Form):
comment = forms.CharField(
widget=forms.TextInput(attrs={'size':'40'}))

我认为必须知道每个字段的本机小部件类型很麻烦,而且为了在表单字段上放一个类名而重写默认值也很有趣。这似乎对我很管用:

class MyForm(forms.Form):
#This instantiates the field w/ the default widget
comment = forms.CharField()


#We only override the part we care about
comment.widget.attrs['size'] = '40'

我觉得这样更干净了。

这里有一个简单的方法来改变观点。在将它传递到模板之前,在视图中添加下面的内容。

form = MyForm(instance = instance.obj)
form.fields['email'].widget.attrs = {'class':'here_class_name'}

还有另一个解决方案,它不需要改变python代码,因此更适合设计师和一次性的表示更改:django-widget-tweaks。希望有人会觉得有用。

使用django-widget-tweaks,它很容易使用并且工作得很好。

否则,这可以使用自定义模板过滤器来完成。

考虑到你这样渲染你的表单:

<form action="/contact/" method="post">
\{\{ form.non_field_errors }}
<div class="fieldWrapper">
\{\{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
\{\{ form.subject }}
</div>
</form>

的形式。subject是BoundField的一个实例,它具有as_widget方法。

你可以在“my_app/templatetags/myfilters.py”中创建一个自定义过滤器“addcss”

from django import template


register = template.Library()


@register.filter(name='addcss')
def addcss(value, arg):
css_classes = value.field.widget.attrs.get('class', '').split(' ')
if css_classes and arg not in css_classes:
css_classes = '%s %s' % (css_classes, arg)
return value.as_widget(attrs={'class': css_classes})

然后应用你的滤镜:

{% load myfilters %}
<form action="/contact/" method="post">
\{\{ form.non_field_errors }}
<div class="fieldWrapper">
\{\{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
\{\{ form.subject|addcss:'MyClass' }}
</div>
</form>

的形式。然后,主题将被“MyClass”css类渲染。

希望这对你有所帮助。

编辑1

编辑2

如果你想要表单中的所有字段都继承一个特定的类,你只需要定义一个父类,从forms.ModelForm继承,然后从它继承

class BaseForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(BaseForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'someClass'




class WhateverForm(BaseForm):
class Meta:
model = SomeModel

这帮助我自动将'form-control'类添加到应用程序的所有表单上的所有字段,而不需要添加代码复制。

事实证明,你可以在表单构造函数(初始化函数)中或在表单类初始化之后这样做。这有时是必需的,如果你不是写自己的形式和形式是来自其他地方-

def some_view(request):
add_css_to_fields = ['list','of','fields']
if request.method == 'POST':
form = SomeForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/thanks/')
else:
form = SomeForm()


for key in form.fields.keys():
if key in add_css_to_fields:
field = form.fields[key]
css_addition = 'css_addition '
css = field.widget.attrs.get('class', '')
field.widget.attrs['class'] = css_addition + css_classes


return render(request, 'template_name.html', {'form': form})

如果你想在表单的字段在模板中中添加一个类(不在view.py或form.py中),比如你想在不覆盖第三方应用程序视图的情况下修改它们,那么Charlesthk 回答中描述的模板过滤器是非常方便的。但是在这个答案中,模板过滤器覆盖了字段可能拥有的任何现有类。

我试图添加这作为一个编辑,但它被建议写作为一个新的答案。

因此,这里有一个模板标签,它尊重字段的现有类:

from django import template


register = template.Library()




@register.filter(name='addclass')
def addclass(field, given_class):
existing_classes = field.field.widget.attrs.get('class', None)
if existing_classes:
if existing_classes.find(given_class) == -1:
# if the given class doesn't exist in the existing classes
classes = existing_classes + ' ' + given_class
else:
classes = existing_classes
else:
classes = given_class
return field.as_widget(attrs={"class": classes})

你也可以使用Django Crispy Forms,如果你想使用Bootstrap或Foundation等CSS框架,它是一个定义表单的好工具。在这里为表单字段指定类很容易。

你的表单类会是这样的:

from django import forms


from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Submit, Field
from crispy_forms.bootstrap import FormActions


class SampleClass(forms.Form):
name = forms.CharField(max_length=30)
age = forms.IntegerField()
django_hacker = forms.BooleanField(required=False)


helper = FormHelper()
helper.form_class = 'your-form-class'
helper.layout = Layout(
Field('name', css_class='name-class'),
Field('age', css_class='age-class'),
Field('django_hacker', css-class='hacker-class'),
FormActions(
Submit('save_changes', 'Save changes'),
)
)

只需将类添加到表单,如下所示。

class UserLoginForm(forms.Form):
username = forms.CharField(widget=forms.TextInput(
attrs={
'class':'form-control',
'placeholder':'Username'
}
))
password = forms.CharField(widget=forms.PasswordInput(
attrs={
'class':'form-control',
'placeholder':'Password'
}
))

你可以试试这个。

class SampleClass(forms.Form):
name = forms.CharField(max_length=30)
name.widget.attrs.update({'class': 'your-class'})
...

你可以在:Django的小部件中看到更多信息

你可以为所有类型的输入字段在这里获取样式选项

小部件是Django对HTML输入元素的表示。小部件处理HTML的呈现,以及从与小部件对应的GET/POST字典中提取数据。

email = forms.EmailField(label='Your email', widget=forms.EmailInput(attrs={'class': 'ui segment teal'}))

如果您正在使用ModelForm,并且已经包含了带有fields属性的必要字段,那么有一种方法可以为它们定义css类。对我来说,这比“for循环”方法更好,因为我想为不同的输入字段使用不同类型的css类。

fields = ( 'date', 'title'),
widgets = {'date': forms.DateInput(attrs={'class': 'datepicker'}),
'title': forms.TextInput(attrs={'class': 'title'})}

或者您也可以尝试通过Form类的构造函数设置它们

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['date'].widget.attrs.update({'class': 'datepicker'})
self.fields['title'].widget.attrs.update({'class':'title'})

要在django中定义css类,你可以在form中使用widgets

例子:

class ProcessForm(forms.ModelForm):
class Meta:
model = Processmachine
fields = ['machine_name', 'operation_no', 'process_uploadfile'] #https://docs.djangoproject.com/en/3.0/ref/forms/widgets/
widgets = { 'machine_name': forms.TextInput(attrs={ 'class': 'form-control' }),
'operation_no': forms.TextInput(attrs={ 'class': 'form-control' }),
'process_uploadfile': forms.ClearableFileInput(attrs={ 'class': 'form-control' }),
}

在上面的形式中,我在attrs中使用了css