What is the most elegant solution to this problem:

I have a form for address information in an ecommerce application.
The user can optionally input a different delivery address - this is done 
via radio button.
In this case the requirement for the delivery address fields change - 
nothing special actually.

What I've done so far:

Model: 

db.define_table('customer',
   Field('name', requires=[IS_NOT_EMPTY()], required=True, notnull=True),
   Field('company',default=None),  
   Field('zip', requires=[IS_MATCH('^[0-9]{5}$', error_message='not a zip 
code')], required=True, notnull=True),
   Field('street', requires=[IS_MATCH("[0-9a-zA-ZäöüÄÖÜ\- \.]+")], 
required=True, notnull=True),
   Field('city', requires=[IS_MATCH("[a-zA-ZäöüÄÖÜ\- \.]+")], required=True, 
notnull=True),
   Field('country', requires=[IS_IN_SET([T('Deutschland'),T('Östereich'), 
T("Schweiz")])], default="Deutschland"),
   Field('email',requires= [IS_NOT_EMPTY(), IS_EMAIL(),
   IS_NOT_IN_DB(db,'customer.email')],
   required=True, notnull=True),
   Field('email_confirmation',requires= [IS_NOT_EMPTY(), IS_EMAIL(),
   IS_NOT_IN_DB(db,'customer.email')],
   required=True, notnull=True),
   Field('delivery_address', 
requires=[IS_IN_SET([T('Yes'),T('No')])],widget=SQLFORM.widgets.radio.widget, 
 default="No"),
   Field('delivery_name',default=None),
   Field('delivery_company',default=None),
   Field('delivery_zip', requires=[IS_EMPTY_OR(IS_MATCH('^[0-9]{0,5}$',
 error_message='not a zip code'))]),
   Field('delivery_street', requires=[IS_EMPTY_OR(IS_MATCH("[a-zA-ZäöüÄÖ\- 
\.]+"))],default=None),
   Field('delivery_city', requires=[IS_EMPTY_OR(IS_MATCH("[a-zA-ZäöüÄÖ\- 
\.]+"))],default=None),
   Field('delivery_country', 
requires=[IS_EMPTY_OR(IS_IN_SET([T('Deutschland'),T('Östereich'), 
T("Schweiz")]))],  default="Deutschland"),
   Field('timestamp', 'datetime', default=request.now, readable=False, 
writable=False)
)

controller:

def address():
   crud.messages.submit_button = 'Weiter zur Bestätigungsseite' 
   crud.settings.formstyle='table2cols'
   form = crud.create(db.customer)
   if form.accepts(request.vars, session, onvalidation=__address_validator):
   response.flash = 'form accepted'
   return dict(form=form)


def __address_validator(form):
   if not form.vars.email == form.vars.email_confirmation:
       form.errors.email_confirmation = "Email-Adressen stimmen nicht 
überein."
   if form.vars.delivery_address == T("Yes"):
      if not form.vars.delivery_name:
         form.errors.delivery_name = "Bitte gib einen Namen ein."
      if not form.vars.delivery_zip:
         form.errors.delivery_zip = "Bitte gib eine Postleitzahl ein."
      if not form.vars.delivery_street:
         form.errors.delivery_street = "Bitte gib eine Straße mit Hausnummer 
ein."
      if not form.vars.delivery_city:
         form.errors.delivery_city = "Bitte gib eine Stadt ein."
      if not form.vars.delivery_country:
         form.errors.delivery_name = "Bitte gib ein Land an."

This works! But it is not very nice to the user, because the check of the 
optional fields happens after the form is accepted.
Is there a better way to set the requirements for the optional fields?

Thanks for help

Reply via email to