2010-11-08 79 views
32

我在这样的模板中输出一个表单域,我想添加一个类(例如,蓝图的span-x -class)到它。所以我想知道是否有一个很好的现成解决方案(模板过滤器),我可以用时尚{{ form.first_name|add_class:"span-4" }}? (我只想知道Django的开发人员或任何人在我自己做这件事之前是否已经想到了这一点)Django:在模板中渲染表单域时添加CSS类

回答

22

为了解决这个问题,我做了我自己的模板过滤器,可以将它应用于任何标签,而不仅仅是输入元素!

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

很好地完成了。为了使它适用于以'/>'结尾的字段,我使用了'return mark_safe(string.replace('','class ='%s''%css_class))' - 使用空格而不是'>'以便它会找到第一个空格并在其余之前注入属性。 – abstractpaper 2012-02-25 15:35:43

+0

正则表达式匹配贪婪,但应匹配懒惰。我已经将上面的代码改为''class_re = re.compile(r'(?<= class = [“\'])(。*?)(?= [”\'])')''。否则它会匹配上一个''''char而不是类尾。 – 2014-01-13 14:32:46

0

您需要明确指定小部件并使用attrs keyword argument添加类。我不知道其他方式。

但是,如果这太麻烦了,您仍然可以将该字段包装到另一个元素中,例如div或span,然后向该类中添加一个类。然后相应地修改你的CSS。

+1

正如我已经提到我我喜欢在模板中使用它,因为表单可以以各种外观呈现! – 2010-11-08 13:41:55

+1

要获得优化的结果,您应该考虑阅读有关响应式布局。你的模板和类应该保持不变,所有的魔法仍然在CSS上。 – 2013-03-16 11:09:18

5

我仍然在学习Django的,但不能这样做这样的事情 -

from django import forms 

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

我想没有必要在模板级别(或使用过滤器)要做到这一点,除非你有一些我不明白的要求。

+2

将样式(css)与功能(表单)分开更清晰。例如,如何使用此方法有条件地向模板中的表单字段添加类?此外,如何在不复制表单的情况下以不同方式显示此表单,例如移动友好表单和不那么友好的表单?表单提供的验证不会改变,但它的视图确实如此。 – varikin 2012-01-24 19:41:30

+1

在表单级应用的CSS类不会影响不同的显示。表单类应该在任何设备上保持不变,并且在需要时您应该具有由设备专用的特定css文件配置。 – 2013-03-16 11:04:51

+0

无论如何,这是大多数情况下的正确答案。无需乱用正则表达式!只是也许还提到了ModelForm的例子: 'class Meta:widgets = {'f':forms.TextInput(attrs = {'class':'name'})}' – frnhr 2014-01-25 20:18:01

12

关于如何使用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' }} 
+1

我发现'class_re'定义有点太贪婪,最后在某些字段中类被输入到'type'属性中,而不是'class'。我的修订版本:'class_re = re.compile(r'(?<= class = [“\'])([^'\'] *)([”\'])')' – DanH 2014-08-05 06:20:25

3

还要说明一点上lazerscience的解决方案:如果你申请这一个<选择不带类属性,字符串>元素在其他情况下更换会产生这样的:

<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)将确保只有“>”将被替换成“类=”一审...“>,这是任何逻辑上是正确表单元素。

+0

Hi ,感谢您的灵感,猜我从来没有用过“select”呢! – 2011-02-13 19:10:47

46

你只需要安装Django widget_tweaks

pip install django-widget-tweaks 

,你可以做你的模板类似的东西后:

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

-

阅读全部内容here

+1

我正在寻找如何向'labels'添加类,我记得手动添加它们很简单:''{ {{ field.label}}' – 2013-11-01 23:22:33

9

另一种方法是在字段上使用as_widget方法来更改它 - 比正则表达式方法更简单,更安全,并且不需要任何其他依赖项。

定义custom template filter

@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

+0

够简单并且可以工作 – Bwire 2015-11-21 15:00:26

+0

喜欢这个优雅的解决方案,再加上我现在学会了如何使用模板标签。谢谢! – Matt 2017-03-30 15:47:14