如何编写自己的 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
数据字典中提取小部件的值。
任何人都可以提供一个简单示例,以便我了解如何完成此操作的基本习惯用法吗?我找不到关于该主题的任何我能理解的有用文档。
为了提供更多上下文,我想创建自己的单选按钮,以特定方式呈现。
我只是在寻找一个非常简单的例子来帮助我理解这个概念。
很难说清楚 "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
数据字典中提取小部件的值。