2010-11-08 85 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