Form生成的label標簽詳解


使用Form生成html標簽的時候,雖然提供了widget的方法可以自定義標簽,但是只能給生成的input標簽添加樣式,對於生成的label標簽無法添加樣式。而很多場景下需要為label和input都添加class以實現自定義樣式。

測試環境

創建一個Form,通過Form幫我們生成HTML:

# urls.py 文件,添加對應關系
 path('email/', views.email),

 

# forms.py 文件 
from django.forms import Form
from django.forms import fields
from django.forms import widgets

class UserEmail(Form):
    username = fields.CharField()
    password = fields.CharField(
        widget=widgets.PasswordInput(attrs={'class': 'c1'})
    )
    email = fields.EmailField(
        widget=widgets.EmailInput(attrs={'class': 'c1'})
    )

 

# views.py 文件 
def email(request):
    obj = forms.UserEmail()
    print(obj['email'].label_tag(attrs={'class': 'c1'}))  # 其實生成標簽的方法是提供attrs參數的
    return render(request, 'demo/email.html', {'obj': obj})

在html中,直接使用Form幫我生成的表單:

<body>
{{ obj.as_p }}
{{ obj.email.label_tag }}
{{ obj.email }}
</body>

這里可以看到,input標簽里都是有class屬性的,但是lable標簽里沒有,並且Form組件里貌似也沒有提供為label標簽增加自定義屬性的方式。

通過模板語言的自定義函數實現

上面的views里的 print(obj['email'].label_tag(attrs={'class': 'c1'})) ,從輸出看,django提供的生成label標簽的方法是支持attrs參數實現自定義屬性的,問題是在前端使用模板語言的時候只能這樣 {{ obj.email.label_tag }} 無法傳入參數。這里就自定義個模板語言的函數來解決這個問題。

自定義函數

要自定義函數,按照下面的步驟操作:

  1. 在APP下,創建templatetags目錄,目錄名字很重要不能錯。
  2. 創建任意 .py 文件,這里文件名隨意,比如:myfun.py。
  3. 文件里創建一個template.Library()對象,名字是register。這里的對象名字必須是register。
  4. 然后寫自己的函數,但是都用@register.simple_tag這個裝飾器裝飾好:

自定義的函數如下:

# app名/templatetags/myfun.py 文件 
from django import template

register = template.Library()

@register.filter(is_safe=True)
def label_with_classes(value, arg):
    return value.label_tag(attrs={'class': arg})

然后在頁面中使用自定義的函數:

<body>
{{ obj.as_p }}
{{ obj.email.label_tag }}
{{ obj.email }}
{% load myfun %}
{{ obj.email|label_with_classes:'c1 c2' }}
</body>

注意,上面的自定義函數引用的時候參數和參數之間一定不能有空格。
這里還有一個好處,把添加前端樣式的代碼放到了前端的html里實現了。

為input標簽也寫一個自定義函數

django默認的方法是在Form里,通過widgets小部件添加attrs參數來實現標簽的自定義樣式。這是在放在后端實現的。上面已經實現了前端的自定義樣式,這里找了到生成input標簽的方法,就是as_widget()。照着樣子再寫一個子定義函數:

# app名/templatetags/myfun.py 文件 
from django import template

register = template.Library()

@register.filter()
def label_with_classes(value, arg):
    return value.label_tag(attrs={'class': arg})

@register.filter()
def widget_with_classes(value, arg):
    return value.as_widget(attrs={'class': arg})

 

最后,上面搞得難么麻煩,主要是為了可以前端一個for循環,就能把表單按自定義的樣式顯示出來:

<body>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
      integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
{% load myfun %}
<form class="form-horizontal">
{% for item in obj %}
    <div class="form-group">
    {{ item|label_with_classes:'col-sm-2 control-label' }}
    <div class="col-sm-10">
        {{ item|widget_with_classes:'form-control' }}
    </div>
    </div>
{% endfor %}
</form>
</body>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM