如何编写自己的 Django 表单小部件? [复制]

Posted

技术标签:

【中文标题】如何编写自己的 Django 表单小部件? [复制]【英文标题】:How do I write my own Django form widget? [duplicate] 【发布时间】:2016-11-05 03:50:57 【问题描述】:

谁能提供一个简单的例子,以便我了解如何做到这一点的基本习惯用法?我找不到任何我能理解的关于该主题的有用文档。

为了提供更多上下文,我想创建自己的单选按钮,以特定方式呈现。

我只是在寻找一个非常简单的例子来帮助我理解这个概念。

【问题讨论】:

该问题中有一条评论指向:tothinkornottothink.com/post/10815277049/… 【参考方案1】:

很难说“一个非常简单的例子”是什么意思。这是一个非常简单的例子:

from django.forms.widgets import Input

class TelInput(Input):
    input_type = 'tel'

但我认为这对你没有多大帮助。

如果您正在寻找示例,最好还是查看django source code。

我认为这应该足以理解它是如何工作的:

from django.utils.encoding import force_text
from django.utils.html import format_html
from django.forms.utils import flatatt

class Widget(...):

    def __init__(self, attrs=None):
        if attrs is not None:
            self.attrs = attrs.copy()
        else:
            self.attrs = 

    def subwidgets(self, name, value, attrs=None, choices=()):
        """
        Yields all "subwidgets" of this widget. Used only by Radioselect to
        allow template access to individual <input type="radio"> buttons.
        Arguments are the same as for render().
        """
        yield SubWidget(self, name, value, attrs, choices)

    def render(self, name, value, attrs=None):
        """
        Returns this Widget rendered as HTML, as a Unicode string.
        The 'value' given is not guaranteed to be valid input, so subclass
        implementations should program defensively.
        """
        raise NotImplementedError('subclasses of Widget must provide a render() method')

    def build_attrs(self, extra_attrs=None, **kwargs):
        "Helper function for building an attribute dictionary."
        attrs = dict(self.attrs, **kwargs)
        if extra_attrs:
            attrs.update(extra_attrs)
        return attrs

    def value_from_datadict(self, data, files, name):
        """
        Given a dictionary of data and this widget's name, returns the value
        of this widget. Returns None if it's not provided.
        """
        return data.get(name)


class Input(Widget):
    """
    Base class for all <input> widgets (except type='checkbox' and
    type='radio', which are special).
    """
    input_type = None  # Subclasses must define this.

    def format_value(self, value):
        if self.is_localized:
            return formats.localize_input(value)
        return value

    def render(self, name, value, attrs=None):
        if value is None:
            value = ''
        final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
        if value != '':
            # Only add the 'value' attribute if a value is non-empty.
            final_attrs['value'] = force_text(self.format_value(value))
        return format_html('<input />', flatatt(final_attrs))

最相关的方法是 render() 将小部件呈现为 HTML 代码,value_from_datadict()POST 数据字典中提取小部件的值。

【讨论】:

请注意,小部件的 HTML 必须有一个 name 属性,否则 Django 管理员将无法读取它们的值,它们将被默默地排除在表单提交之外。 @AlanPorter 这由final_attrs = self.build_attrs(attrs, type=self.input_type, name=name) 处理。名称由表单决定,而不是小部件本身。在幕后,Django 将字段名称传递给render() 方法。 啊,是的...我并不是要暗示这个例子是因为那个缺失的名字。我正在使用在博客上找到的另一个示例,我花了两天时间调试它。我只是希望任何跟随我所遵循的相同路径的人都小心地包含这个名字。谢谢,@Antoine-Pinsard!

以上是关于如何编写自己的 Django 表单小部件? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Django:如何更改内联表单集中的字段小部件

如何将日期/日历小部件添加到 django 表单?

如何修改 Django 中特定类型的所有内置表单字段的默认小部件?

如何在 Select 小部件中构造带有模型对象的 Django 表单?

动态自定义 django 表单小部件

如何对 Django Select 小部件中的选择进行分组?