Django:如何构建自定义表单小部件?

Nic*_*ner 52 python forms django

我很难找到有关如何编写自定义小部件的文档.

我的问题是:

  • 如果我构建自定义窗口小部件,它是否可以等效地用于管理界面或普通表单?
  • 如果我想允许用户编辑项目列表,我应该将哪个小部件子类化?我需要覆盖/实现哪些小部件方法?
  • 什么小部件方法负责从用户的输入回到数据模型?

谢谢.

And*_*Dog 48

你说得对,Django没有提供有关这个特定主题的文档.我建议你看看内置的小部件django.forms.widgets(我将从下面的模块中引用类).

如果我构建自定义窗口小部件,它是否可以等效地用于管理界面或普通表单?

管理员会覆盖一些小部件(请参阅参考资料django.contrib.admin.options.FORMFIELD_FOR_DBFIELD_DEFAULTS).您可以继承子类ModelAdmin并更改formfield_overrides属性,但我从未做过任何事情,ModelAdmin所以我在这里无法帮助...

如果我想允许用户编辑项目列表,我应该将哪个小部件子类化?我需要覆盖/实现哪些小部件方法?

您的窗口小部件可能与默认窗口小部件没有任何共同之处(Select如果有的话?).子类来自Widget和如果你发现内置的任何常见模式,你仍然可以在以后更改它.

实现以下方法:

  • render(self, name, value, attrs=None, renderer=None)

    查看Input.render一个简单的例子.它还支持HTML中包含的用户定义属性.您可能还想添加"id"属性,请参阅MultipleHiddenInput.render如何执行此操作.不要忘记mark_safe直接输出HTML时使用.如果您有一个相当复杂的小部件,则可以使用模板渲染(示例).

  • _has_changed(self, initial, data)

    可选的.在admin中用于记录有关更改内容的消息.

什么小部件方法负责从用户的输入回到数据模型?

这与小部件无关 - Django无法知道在先前的请求中使用了哪个小部件.它只能使用从表单发送的表单(POST)数据.因此,field方法Field.to_python用于将输入转换为Python数据类型(ValidationError如果输入无效,则可能会引发).

  • @AndiDog - 实际上小部件通过`value_from_datadict`方法转换POST数据 - 它与小部件的`render`方法相反.这个方法可能就是小部件上的Django文档所说的"小部件处理HTML的呈现,以及从与小部件对应的GET/POST字典中提取数据". (3认同)

Wto*_*wer 22

Django <1.11

除了其他答案,这是自定义小部件的一个小代码示例:

widgets.py:

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


class MyWidget(Widget):
    template_name = 'myapp/my_widget.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)

my_widget.html:

<textarea id="mywidget-{{ widget.name }}" name="{{ widget.name }}">
{% if widget.value %}{{ widget.value }}{% endif %}</textarea>
Run Code Online (Sandbox Code Playgroud)

Django 1.11

现在使用表单呈现API呈现窗口小部件.


Gho*_*r21 5

注意:这里有三个问题.对于前两个问题,请参阅AndiDog的更全面的答案.我这里只回答第三个问题:

问:什么样的窗口小部件方法负责从用户的输入回到数据模型?

A. value_from_datadict方法 - 它是小部件render方法的反转.这个方法可能就是小部件上的Django文档所说的"小部件处理HTML的呈现,以及从与小部件对应的GET/POST字典中提取数据".在文档中没有进一步的这一点,但你可以从内置小部件的代码中看到它是如何工作的.