在项目中,我们通常会用django中的modelform帮助我们快速生成前端的样式,提升开发效率。但是有时,当我们需要让一些字段,显示一些特殊的样式时,就需要对modelform中的默认样式,手动进行一些修改:
选择颜色 示例
颜色选项,本来在数据库中是choices字段(字段名直接使用css样式中的颜色代码,方便后面自定义操作),在modelfrom自动渲染是一个select标签,如下图
通过自定义的修改标签样式,可以改变标签的类型,并配合前端的一些技巧,最终修改后的效果如下。
新建widgets.py,创建ColorRadioSelect类,继承django的RadioSelect类
可以直接改成radio标签
class ColorRadioSelect(RadioSelect):pass
在modelform中对color 字段设置属性
class ProjectModelForm(forms.ModelForm):class Meta:model = models.Projectfields = "__all__"widgets = {'desc': forms.Textarea,'color': ColorRadioSelect(attrs={'class': 'color-radio'})}
这样我们就能看到页面的效果如下
通过查看RadioSelect类源码,可以看到三个参数,从参数名可以大概猜到其意思,其中我们要修改template_name和option_template_name。
class RadioSelect(ChoiceWidget):input_type = 'radio'template_name = 'django/forms/widgets/radio.html'option_template_name = 'django/forms/widgets/radio_option.html'
下面我们对这两个属性,自定义模板,修改的时候参考源码
radio.html继承的是mutiple_input.html
{% include "django/forms/widgets/multiple_input.html" %}
继续看mutiple_input.html
{% with id=widget.attrs.id %}<ul{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %}<li>{{ group }}<ul{% if id %} id="{{ id }}_{{ index }}"{% endif %}>{% endif %}{% for option in options %}<li>{% include option.template_name with widget=option %}</li>{% endfor %}{% if group %}</ul></li>{% endif %}{% endfor %}</ul>{% endwith %}
我们自定义修改成如下样式:
{% with id=widget.attrs.id %}<div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% for option in options %}<label {% if option.attrs.id %} for="{{ option.attrs.id }}"{% endif %} >{% include option.template_name with widget=option %}</label>{% endfor %}{% endfor %}</div>{% endwith %}
radio_option.html修改如下,增加一个span标签,样式修改成圆形,背景色即label的值,即(css颜色值)
{% include "django/forms/widgets/input.html" %}<span class="cycle" style="background-color:{{option.label }}"></span>
最后在html页面增加css样式,思路是吧input(radio)框放在span的上面,让用户感觉是在点圆圈,实际是在点圆圈上的input框
<style>.color-radio label {margin-left: 0;padding-left: 0;}.color-radio input[type="radio"] {display: none;}.color-radio input[type="radio"] + .cycle {display: inline-block;height: 20px;width: 20px;border-radius: 50%;border: 2px solid #dddddd;}.color-radio input[type="radio"]:checked + .cycle {border: 2px solid black;}</style>
大功告成
通过这个颜色的案例,我们大概了解了django对于input框格式的实现方式,便可以在其基础上,稍加修改,自定义我们想要的效果。
以后有其他需求,不仅针对modelform,比如form,都可以参考这个方法,来自己试试吧