次のように、CSS クラスとスタイルをフィールドに追加できます。
phone = TextField(label='Phone',
validator=twc.Required,
css_class='MyTextFieldClass',
attrs=dict(style='display:block;width:8em', maxlength='12'))
完全に異なるレイアウトについては、http: //tw2core.readthedocs.org/en/latest/design/#templateBaseLayout
で説明されているように、独自のテンプレートをサブクラス化して参照する必要があります。
たとえば、FloatLayout というより柔軟な Layout クラスを作成しました。
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>
具体的な 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