Python Django:Form或Field类如何呈现小部件?什么';过程是什么?
我已经实现了一个扩展Python Django:Form或Field类如何呈现小部件?什么';过程是什么?,python,django,forms,validation,widget,Python,Django,Forms,Validation,Widget,我已经实现了一个扩展Widget的类,我需要为这个类实现一个验证系统,但我认为它与Field类不兼容,因为我已经应用了自定义render()方法,这可能违反了(不确定)。以下是一个例子: from django import forms from django.utils.safestring import mark_safe from django.utils.encoding import force_unicode from django.utils import formats from
Widget
的类,我需要为这个类实现一个验证系统,但我认为它与Field
类不兼容,因为我已经应用了自定义render()
方法,这可能违反了(不确定)。以下是一个例子:
from django import forms
from django.utils.safestring import mark_safe
from django.utils.encoding import force_unicode
from django.utils import formats
from django_future import format_html, flatatt
class InputGeneric(forms.Widget):
"""
Base class for all <input> widgets
"""
input_type = None # Subclasses must define this.
_to_str = None
def __init__(self, attrs=None, single_attrs=None):
super(InputGeneric, self).__init__(attrs)
self.single_attrs = single_attrs or ''
def get_attrs(self):
return self.attrs
def get_attr(self, key):
return self.attrs.get(key, None)
def render(self, name=None, value=None, attrs=None, single_attrs=None):
'''
*The default arguments of this function are:
(self, name, value, attrs=None)
- - - -
single_attrs: is a string of HTML5 single attributes like "required", disabled"
Example:
render(single_attrs='required disabled')
'''
name = name or self.attrs.get('name', None)
if name:
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
else:
final_attrs = self.build_attrs(attrs, type=self.input_type)
value = self.attrs.get('value', None)
if value:
# Only add the 'value' attribute if a value is non-empty.
final_attrs['value'] = force_unicode(self._format_value(value))
self._to_str = format_html('<input{0} {1} />', flatatt(final_attrs), single_attrs)
return self._to_str
def get_rendered(self):
return self.render(attrs=self.attrs, single_attrs=self.single_attrs)
def __str__(self):
if self._to_str:
return self._to_str
self._to_str = self.render()
return self._to_str
class InputText(InputGeneric):
input_type = 'text'
def __init__(self, attrs=None, single_attrs=None):
if attrs.get('type', None) is not None:
del attrs['type']
super(InputText, self).__init__(attrs, single_attrs)
因此,我想问一下字段
类(或表单
类)如何从小部件
获取原始值(html),以及如何应用验证过滤器并返回结果。请提供一个带有说明的小示例,以了解流程
*注意我已经看过[Django代码][3],不幸的是我无法完全理解这个过程
首先,我不得不说我的方法是不正确的。从
render()
的参数中删除name
和value
是错误的决定,因为这确实违反了LSP原则。此外,输入字段最基本的内容是name
和value
,它们也包含在POST请求中
之后,我发现了内部的渲染过程。小部件在BoundField()
类中呈现,该类在调用时自动调用as\u小部件()
函数。渲染的所有过程也是如此
接下来,我用一个示例应用程序演示这个过程
应用程序结构
1) 首先,我们要上表单课: my_form.py: 3) 模板: contact.html 3) 上面的函数调用另一个名为
self.\u html\u output(…)
的函数,当然,它位于BaseForm()中。此函数负责输出通过调用其他较小的函数或类呈现的最终结果
一些注释
- 当在views.py内执行
form=ContactForm()
时,我们知道称为ContactForm()
类。但是这个类是生活在forms.py中的Form
的子类,Form()
也是BaseForm()
类的子类。这意味着ContactForm()
继承了BaseForm()
的所有内容
Form()
类为空。仅继承自BaseForm()
,用于继承目的。每个表单的真正父级是BaseForm()
class
- 在初始化时,
ContactForm()
和他的父母Form()
和BaseForm()
调用一些非常重要的变量,例如self.fields
,其中包含孩子的所有字段。在我们的示例中:主题
,电子邮件
,消息
。
其他重要变量包括:
self.data
:包含POST数据
self.\u errors
:调用clean()后存储错误
\u html\u output()的内部
此函数迭代self.fields
(在我们的例子中是通过subject
,email
,message
)并为每个字段调用类BoundField()
,如下所示:
bf=BoundField(frm\u clss,field,name)
第一个参数frm\u clss
是BaseForm()
类。第二个是字段列表中的当前字段(例如,主题
),第三个是ContactForm()
中给出的字段的实际名称,因此这三个名称是:“主题”、“电子邮件”和“消息”
最后,该函数返回所有呈现的小部件的“已编译”和标记的安全字符串
output.append(normal_row % {
'errors': force_unicode(bf_errors),
'label': force_unicode(label),
'field': unicode(bf),
'help_text': help_text,
'html_class_attr': html_class_attr
})
.
.
.
return mark_safe(u'\n'.join(output))
BoundField()类
默认情况下,调用小部件的render()
方法,并将html字符串返回到BaseForm()
类(\u html\u output()
)。首先,我必须说我的方法不正确。从render()
的参数中删除name
和value
是错误的决定,因为这确实违反了LSP原则。此外,输入字段最基本的内容是name
和value
,它们也包含在POST请求中
之后,我发现了内部的渲染过程。小部件在BoundField()
类中呈现,该类在调用时自动调用as\u小部件()
函数。渲染的所有过程也是如此
接下来,我用一个示例应用程序演示这个过程
应用程序结构
1) 首先,我们要上表单课:
my_form.py:
3) 模板:
contact.html
3) 上面的函数调用另一个名为self.\u html\u output(…)
的函数,当然,它位于BaseForm()中。此函数负责输出通过调用其他较小的函数或类呈现的最终结果
一些注释
- 当在views.py内执行
form=ContactForm()
时,我们知道称为ContactForm()
类。但是这个类是生活在forms.py中的Form
的子类,Form()
也是BaseForm()
类的子类。这意味着ContactForm()
继承了BaseForm()
的所有内容
Form()
类为空。仅继承自BaseForm()
,用于继承目的。每个表单的真正父级是BaseForm()
class
- 在初始化时,
ContactForm()
和他的父母Form()
和BaseForm()
调用一些非常重要的变量,例如self.fields
,其中包含孩子的所有字段。在我们的示例中:主题
,电子邮件
,消息
。
其他重要变量包括:
self.data
:
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(min_length = 2, max_length = 100, widget = forms.TextInput(attrs = {'placeholder':'Type a subject...'}))
email = forms.EmailField(required=True, widget = forms.TextInput(attrs={'class': 'span3', 'placeholder': 'Your email...'}))
message = forms.CharField(widget=forms.Textarea(attrs={'rows': '5', 'placeholder': 'Type a message...'}))
def clean_message(self):
message = self.cleaned_data['message']
num_words = len(message.split())
if num_words < 4:
raise forms.ValidationError("Not enough words!")
return message
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
try:
send_mail(
cd['subject'],
cd['message'],
cd.get('email', 'noreply@anonymous.com'),
['myemail@ahost.com'],
)
except BadHeaderError:
return HttpResponse('Invalid header found.')
return HttpResponseRedirect('thank-you/')
else:
form = ContactForm()
return render_to_response('/contact.html', {'form': form})
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="" method="post">
<fieldset>
<legend>Contact</legend>
<div class="field">
{{ form.subject.errors }}
</div>
{{ form.as_table }}
<br />
<button type="submit" class="btn">Submit</button>
</fieldset>
</form>
def as_table(self):
"Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
return self._html_output(
normal_row = u'<tr%(html_class_attr)s><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>',
error_row = u'<tr><td colspan="2">%s</td></tr>',
row_ender = u'</td></tr>',
help_text_html = u'<br /><span class="helptext">%s</span>',
errors_on_separate_row = False)
output.append(normal_row % {
'errors': force_unicode(bf_errors),
'label': force_unicode(label),
'field': unicode(bf),
'help_text': help_text,
'html_class_attr': html_class_attr
})
.
.
.
return mark_safe(u'\n'.join(output))