如何在Django Forms中为密码字段设置圆点占位符
问题
使用Django Forms渲染注册页面时,尝试通过widgets为密码字段设置•字符实体作为占位符,但页面渲染后,占位符被转为•,无法正常显示圆点符号。以下是相关代码:
forms.py
class Signup(forms.ModelForm): class Meta: model = User fields = ["username", "email", "password", "password2", "library_no", "first_name", "last_name",] help_texts = { "username":None, } labels = { } widgets = { "username": forms.TextInput(attrs={ "id":"input_46", "name":"q46_typeA46", "data-type":"input-textbox", "class":"form-textbox validate[required]", "size":"310", "data-component":"textbox", "aria-labelledby":"label_46", "placeholder":"180591001" }), "first_name":forms.TextInput(attrs={ "id":"first_4", "name":"q4_name[first]", "class":"form-textbox validate[required]", "autoComplete":"section-input_4 given-name", "data-component":"first", "aria-labelledby":"label_4 sublabel_4_first", "required":True, "placeholder":"Chinedu" }), "last_name":forms.TextInput(attrs={ "id":"last_4", "name":"q4_name[last]", "class":"form-textbox validate[required]", "autoComplete":"section-input_4 family-name", "data-component":"last", "aria-labelledby":"label_4 sublabel_4_last", "required":True, "placeholder":"Oladapo Dikko" }), "email":forms.EmailInput(attrs={ "id":"input_10", "name":"q10_email10", "class":"form-textbox validate[required, Email]", "placeholder":"ex: myname@example.com", "data-component":"email", "aria-labelledby":"label_10 sublabel_input_10", "required":True }), "password": forms.PasswordInput(attrs={ "id":"first_50", "name":"q50_name50[first]", "class":"form-textbox", "autoComplete":"section-input_50 given-name", "data-component":"first", "aria-labelledby":"label_50 sublabel_50_first", "required":True, "placeholder":"••" }), "password2": forms.PasswordInput(attrs={ "id":"last_50", "name":"q50_name50[last]", "class":"form-textbox", "autoComplete":"section-input_50 family-name", "data-component":"last", "aria-labelledby":"label_50 sublabel_50_last", "required": False }), "library_no": forms.TextInput(attrs={"required": False}), }
signup.html
<!DOCTYPE html> <html class="supernova"> <head> <title>SignUp</title> <style type="text/css">@media print{.form-section{display:inline!important}.form-pagebreak{display:none!important}.form-section-closed{height:auto!important}.page-section{position:initial!important}}</style> <link rel="stylesheet" href="/static/signup/css/style.css"> <link rel="stylesheet" href="/static/signup/css/main.css"> </head> <body> <form class="jotform-form" action="/signup/" method="post" name="form_230023299150548" id="230023299150548" accept-charset="utf-8" autocomplete="on"> {%csrf_token%} <div role="main" class="form-all"> <style> .form-all:before { background: none; } </style> <ul class="form-section page-section"> <li id="cid_28" class="form-input-wide" data-type="control_head"> <div class="form-header-group header-large"> <div class="header-text httal htvam"> <h1 id="header_28" class="form-header" data-component="header">SignUp</h1> </div> </div> </li> <li class="form-line jf-required" data-type="control_textbox" id="id_46"> <label class="form-label form-label-top form-label-auto" id="label_46" for="input_46"> Username <span class="form-required">*</span> </label> <div id="cid_46" class="form-input-wide jf-required" data-layout="half"> {{form.username}} </div> </li> <li class="form-line jf-required" data-type="control_fullname" id="id_4"> <div id="cid_4" class="form-input-wide jf-required" data-layout="full"> <div data-wrapper-react="true"> <span class="form-sub-label-container" style="vertical-align:top" data-input-type="first"> <label class="form-label form-label-top" id="label_4" for="first_4"> First Name <span class="form-required">*</span> </label> {{form.first_name}} </span> <span class="form-sub-label-container" style="vertical-align:top" data-input-type="last"> <label class="form-label form-label-top" id="label_4" for="first_4"> Last Name <span class="form-required">*</span> </label> {{form.last_name}} </span> </div> </div> </li> <li class="form-line jf-required" data-type="control_email" id="id_10"> <label class="form-label form-label-top form-label-auto" id="label_10" for="input_10"> E-mail <span class="form-required">*</span> </label> <div id="cid_10" class="form-input-wide jf-required" data-layout="half"> <span class="form-sub-label-container" style="vertical-align:top"> {{form.email}} </span> </div> </li> <li class="form-line" data-type="control_fullname" id="id_50"> <div id="cid_50" class="form-input-wide" data-layout="full"> <div data-wrapper-react="true"> <span class="form-sub-label-container" style="vertical-align:top" data-input-type="first"> <label class="form-label form-label-top form-label-auto" id="label_50" for="first_50"> Password <span class="form-required">*</span> </label> {{form.password}} </span> <span class="form-sub-label-container" style="vertical-align:top" data-input-type="last"> <label class="form-label form-label-top form-label-auto" id="label_50" for="first_50">Confirm Password <span class="form-required">*</span> </label> {{form.password2}} </span> </div> </div> </li>
解决方案
问题根源是Django会自动转义HTML字符实体,把&转为&,导致•无法被浏览器解析为圆点。可以通过以下两种方法解决:
方法1:直接使用Unicode圆点字符
不需要使用HTML实体,直接在placeholder中写入Unicode的圆点字符•,Django不会转义普通Unicode字符,浏览器会直接显示为圆点。
修改forms.py中password字段的placeholder:
"password": forms.PasswordInput(attrs={ # 其他属性保持不变 "placeholder": "••" # 直接使用Unicode圆点字符 }),
方法2:在模板中关闭字段的自动转义
如果一定要使用HTML实体,可以在模板渲染该字段时,使用|safe过滤器告诉Django不需要转义这个字段的内容。
修改signup.html中的密码字段渲染代码:
{{form.password|safe}}
同时确认password2字段如果需要同样效果也做对应修改:
{{form.password2|safe}}
注意:使用|safe时要确保字段内容是可信的,避免XSS风险,这里因为是自己设置的占位符,所以安全风险极低。
内容的提问来源于stack exchange,提问作者Olasubomi
相关产品推荐
相关产品推荐

