如何编写自己的 Django 表单小部件?

How do I write my own Django form widget?

任何人都可以提供一个简单示例,以便我了解如何完成此操作的基本习惯用法吗?我找不到关于该主题的任何我能理解的有用文档。

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

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

很难说清楚 "a very simple example" 是什么意思。这是一个非常简单的例子:

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 数据字典中提取小部件的值。