Django 自定义小部件渲染

rob*_*ter 3 django django-forms django-widget

一般问题

假设你有某个型号

class MyModel(models.Model):
    Name = models.CharField(max_length=64)
Run Code Online (Sandbox Code Playgroud)

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

class CreateMyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['name']
Run Code Online (Sandbox Code Playgroud)

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

{%for field in form%}
{{field}}
{%endfor%}
Run Code Online (Sandbox Code Playgroud)

当需要自定义样式时,我通常不得不将我的<div>s 和s 放入该循环中,并在子类中<span>指定基本小部件及其。attrsMeta

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

具体问题

假设我有一个模板,其中TextInput需要呈现表单,如下模板所示

<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>
Run Code Online (Sandbox Code Playgroud)

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

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

我知道占位符是我可以放入 的attrs初始化中的东西TextInput,但插件(或本例中的父 div)不是或至少据我所知不是

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

anj*_*505 7

我们可以像下面这样做。

小部件

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)
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

  • 请注意,小部件的 HTML 必须具有名称属性,否则 Django 管理员将无法读取它们的值,并且它们将被默默地排除在表单提交之外。 (2认同)