您可以将 CSS 类和样式添加到您的字段,如下所示:
phone = TextField(label='Phone',
validator=twc.Required,
css_class='MyTextFieldClass',
attrs=dict(style='display:block;width:8em', maxlength='12'))
对于完全不同的布局,您需要继承BaseLayout
并引用您自己的模板,如下所述:http: //tw2core.readthedocs.org/en/latest/design/#template。
例如,我创建了一个更灵活的 Layout 类,称为 FloatLayout:
from itertools import groupby
from tw2.core import Param
from tw2.forms.widgets import BaseLayout
class FloatLayout(BaseLayout):
template = "widgets.templates.float_layout"
aside = Param('All fields aside', default=False)
def rows(self, children):
"""Create the rows."""
def row_no(child, no=[0]):
if not self.aside and not getattr(child, 'aside', False):
no[0] += 1
return no[0]
return groupby(children, row_no)
它可以与这个 FloatForm 类一起使用:
from tw2.core import Variable
from tw2.forms import Form
class FloatForm(Form):
"""Form using floating divisions allowing multiple fields per row.
Fields having the 'aside' attribute set appear on the same row.
Something like the following should be included in the site CSS file:
form.floatform {
margin-bottom: 1ex;
}
form.floatform div.row {
clear: left;
overflow: hidden;
height: 100%;
margin-top: 1.5ex;
}
form.floatform div.field {
float: left;
margin-right: 1em;
}
form.floatform label.fieldlabel {
display: block;
}
form.floatform div.submit {
margin-top: 3ex;
}
"""
template = "widgets.templates.float_form"
child = Variable(default=FloatLayout)
css_class = "floatform"
FloatLayout 的 Genshi 模板 float_layout.html 是这样的:
<div xmlns:py="http://genshi.edgewall.org/" py:attrs="w.attrs" py:strip="True">
<div py:for="row_no, row in w.rows(w.children_non_hidden)"
class="${row_no % 2 and 'odd' or 'even'} row">
<div py:for="child in row" py:attrs="child.container_attrs"
class="field${child.validator and
getattr(child.validator, 'required', None) and ' required' or ''}"
title="${w.hover_help and w.help_text or ''}">
<label py:if="child.label" for="${child.attrs.get('id')}"
class="fieldlabel" py:content="child.label"/>
<span py:replace="child.display()"/>
<span py:if="not w.hover_help and child.help_text"
class="fieldhelp" py:content="child.help_text"/>
<span py:if="child.error_msg"
class="fielderror" py:content="child.error_msg"/>
</div>
</div>
<div py:if="w.children_hidden" style="display:none">
<div py:for="child in w.children_hidden" py:replace="child.display()"/>
</div>
</div>
FloatForm 的 Genshi 模板 float_form.html 是这样的:
<form xmlns:py="http://genshi.edgewall.org/"
class="floatform" py:attrs="w.attrs">
<div py:if="w.error_msg" class="formerror" py:content="w.error_msg"/>
<div py:if="w.help_msg" class="formhelp"><p py:content="w.help_msg"/></div>
<div py:replace="w.child.display()"/>
<div py:for="button in w.buttons" class="field" py:content="button.display()"/>
</form>
一个具体的表单现在看起来像这样:
class UserForm(FloatForm):
action = url('save_user')
submit = SubmitButton('Save user')
user_id = HiddenField(validator=IntValidator())
user_name = TextField(validator=UserNameValidator(max=16),
size=20, maxlength=16, label=u'User name:')
remote_account = CheckBox(validator=BoolValidator(),
label=u'Remote account:', aside=True)
new_password = PasswordField(
validator=PasswordValidator(required=False),
size=20, maxlength=16, label=u'Password:', aside=True)
group_id = CheckBoxList(item_validator=IntValidator(),
label=u'Roles:', css_class='inline')
display_name = TextField(validator=NameValidator(max=255),
size=64, maxlength=255, label=u'Real name:')
mail = TextField(validator=EmailIfLocalValidator(),
size=64, maxlength=255, label=u'Email address:')
如您所见,字段remote_account
有new_password
一个属性aside
,使它们与 出现在同一行上user_name
。