Add a custom widget for address

This commit is contained in:
Frédéric Péters 2011-08-18 19:17:17 +02:00
parent 5bf5e3364b
commit 853befcdb2
5 changed files with 168 additions and 27 deletions

View File

@ -0,0 +1,77 @@
from zope.interface import Interface
from zope import schema
from zope.schema import Object, Field
from zope.schema.interfaces import IObject, IField, IFromUnicode
from zope.interface import implements, implementer
from zope.component import adapts, adapter, provideAdapter
from z3c.form.interfaces import IFormLayer, IFieldWidget, NOVALUE
from z3c.form.widget import Widget, FieldWidget
from z3c.form.interfaces import IWidget
from z3c.form.converter import BaseDataConverter
from themis.datatypes.interfaces import MessageFactory as _
class IAddress(IField):
title = schema.TextLine(title=_(u'Title'), required=False)
street = schema.TextLine(title=_(u'Street'), required=False)
zipcode = schema.TextLine(title=_(u'Zip'), required=False)
city = schema.TextLine(title=_(u'City'), required=False)
phone1 = schema.TextLine(title=_(u'Phone'), required=False)
phone2 = schema.TextLine(title=_(u'Phone 2'), required=False)
fax = schema.TextLine(title=_(u'Fax'), required=False)
email = schema.TextLine(title=_(u'Email'), required=False)
class Address(Field):
implements(IAddress, IFromUnicode)
title = None
street = None
zipcode = None
city = None
phone1 = None
phone2 = None
fax = None
email = None
class IAddressWidget(IWidget):
pass
class AddressWidget(Widget):
implements(IAddressWidget)
def update(self):
super(AddressWidget, self).update()
def extract(self, default=NOVALUE):
if not (self.name + '.street') in self.request.form:
return NOVALUE
address = Address()
has_value = None
for attr in ('title', 'street', 'zipcode', 'city', 'phone1', 'phone2',
'fax', 'email'):
setattr(address, attr, self.request.get(self.name + '.' + attr))
has_value = has_value or getattr(address, attr)
if not has_value:
return NOVALUE
return address
@adapter(IAddress, IFormLayer)
@implementer(IFieldWidget)
def AddressFieldWidget(field, request):
"""IFieldWidget factory for Address."""
return FieldWidget(field, AddressWidget(request))
class AddressConverter(BaseDataConverter):
adapts(IAddress, IAddressWidget)
def toWidgetValue(self, value):
if value is None:
return Address()
return value
def toFieldValue(self, value):
return value

View File

@ -0,0 +1,13 @@
<div lang="en"
xml:lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
i18n:domain="plone.app.textfield"
tal:attributes="id view/id">
<tal:define define="fieldName view/name">
TODO
</tal:define>
</div>

View File

@ -0,0 +1,61 @@
<div lang="en"
xml:lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
i18n:domain="plone.app.textfield"
tal:attributes="id view/id">
<tal:define define="fieldName view/name">
<style type="text/css">
.address { margin-left: 2em; }
</style>
<div class="address">
<div class="fieldTitle">
<label>Title</label>
<input type="text" tal:attributes="id string:${fieldName}_title;
name string:${fieldName}.title;
value view/value/title"/>
</div>
<div class="fieldStreet">
<label>Street</label>
<input type="text" tal:attributes="id string:${fieldName}_street;
name string:${fieldName}.street;
value view/value/street"/>
</div>
<div class="fieldZipCode">
<label>Zip Code</label>
<input type="text" size="6" tal:attributes="id string:${fieldName}_zipcode;
name string:${fieldName}.zipcode;
value view/value/zipcode"/>
<label>City</label>
<input type="text" tal:attributes="id string:${fieldName}_city;
name string:${fieldName}.city;
value view/value/city"/>
</div>
<div class="fieldContacts">
<label>Phone</label>
<input type="text" tal:attributes="id string:${fieldName}_phone1;
name string:${fieldName}.phone1;
value view/value/phone1"/>
<label>Phone (2)</label>
<input type="text" tal:attributes="id string:${fieldName}_phone2;
name string:${fieldName}.phone2;
value view/value/phone2"/>
<br/>
<label>Fax</label>
<input type="text" tal:attributes="id string:${fieldName}_fax;
name string:${fieldName}.fax;
value view/value/fax"/>
<label>Email</label>
<input type="text" tal:attributes="id string:${fieldName}_email;
name string:${fieldName}.email;
value view/value/email"/>
</div>
</div>
</tal:define>
</div>

View File

@ -2,6 +2,8 @@
xmlns="http://namespaces.zope.org/zope"
xmlns:grok="http://namespaces.zope.org/grok"
xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
xmlns:z3c="http://namespaces.zope.org/z3c"
xmlns:browser="http://namespaces.zope.org/browser"
i18n_domain="themis.datatypes">
<!-- Include configuration for dependencies listed in setup.py -->
@ -27,6 +29,19 @@
provides="themis.datatypes.deputy.INameFromPersonNames"
factory="themis.datatypes.deputy.NameFromPersonNames" />
<adapter factory=".deputy.AddressFieldWidget"/>
<adapter factory=".address.AddressFieldWidget"/>
<adapter factory=".address.AddressConverter"/>
<z3c:widgetTemplate
mode="display"
widget=".address.IAddressWidget"
layer="z3c.form.interfaces.IFormLayer"
template="address_display.pt"/>
<z3c:widgetTemplate
mode="input"
widget=".address.IAddressWidget"
layer="z3c.form.interfaces.IFormLayer"
template="address_input.pt"/>
</configure>

View File

@ -21,36 +21,11 @@ from z3c.form.browser.text import TextWidget
from z3c.form.interfaces import IFormLayer, IFieldWidget
from z3c.form.widget import FieldWidget
from themis.datatypes.interfaces import MessageFactory as _
from themis.datatypes.polgroup import IPolGroup
class IAddress(IField):
title = schema.TextLine(title=_(u'Title'), required=False)
street = schema.TextLine(title=_(u'Street'), required=False)
zipcode = schema.TextLine(title=_(u'Zip'), required=False)
city = schema.TextLine(title=_(u'City'), required=False)
phone1 = schema.TextLine(title=_(u'Phone'), required=False)
phone2 = schema.TextLine(title=_(u'Phone 2'), required=False)
fax = schema.TextLine(title=_(u'Fax'), required=False)
email = schema.TextLine(title=_(u'Email'), required=False)
class Address(Field):
implements(IAddress, IFromUnicode)
def fromUnicode(self, str):
return None
def __str__(self):
return u'/'.join([x for x in (self.title, self.street, self.zipcode, self.city) if x])
@adapter(IAddress, IFormLayer)
@implementer(IFieldWidget)
def AddressFieldWidget(field, request):
"""IFieldWidget factory for Address."""
return FieldWidget(field, TextWidget(request))
from address import Address
class IDeputy(form.Schema):
firstname = schema.TextLine(title=_(u'First Name'))