Django 自定义小部件渲染

Django Custom widget rendering

一般问题

假设你有某个型号

class MyModel(models.Model):
    Name = models.CharField(max_length=64)

以及您用于创作的随附表格

class CreateMyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['name']

在正常情况下,当表单在模板中呈现时我通常循环遍历模板中的字段

{%for field in form%}
{{field}}
{%endfor%}

当需要自定义样式时,我通常不得不求助于将我的 <div>s 和 <span>s 放在那个循环中,并在Meta 子类。

查看关于该主题的 Django Documentation,我明白似乎我必须使用 Media 子类才能使所有操作发生在 widgets 属性 在 Meta 中,但我无法理解它。

具体问题

假设我有一个模板,其中 TextInput 表单需要呈现 as in this template:

<div class="form-group input-group">
    <span class="input-group-addon">Name</span>
        <input type="text" name="name" class="form-control" placeholder="MyModel Name">
</div>

我如何着手创建一个小部件,以便我可以通过使用获得相同的结果:

class CreateMyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['name']
        widgets={'name':MyWidget(addon="Name",placeholder="MyModel Name")}

我知道占位符是我可以放在 TextInputattrs 初始化中的东西,但是插件(或父 div,在这种情况下)不是 或者至少据我所知

很抱歉问了一个很长的问题,我只是觉得我需要彻底解释这个问题,因为它已经困扰了我一段时间...

我们可以像下面那样做。

小工具

from django import forms
from django.template import loader
from django.utils.safestring import mark_safe


class MyWidget(forms.Widget):
    template_name = 'widget_template.html'

    def get_context(self, name, value, attrs=None):
        return {'widget': {
            'name': name,
            'value': value,
        }}

    def render(self, name, value, attrs=None):
        context = self.get_context(name, value, attrs)
        template = loader.get_template(self.template_name).render(context)
        return mark_safe(template)

widget_template.html

<div class="form-group input-group">
    <span class="input-group-addon">Name</span>
        <input type="text" class="form-control" id="mywidget-{{ widget.name }}" name="{{ widget.name }}" />
</div>