Python and Web: Building Dynamic Web Forms in Web2Py from Ground – Part III

Welcome to the third and final tutorial in the series of creating dynamic web forms using Web2Py.

In the second tutorial of this series, we talked about editing/updating/deleting the submitted form records as well as management of those records using an ingenious function named SQLFORM.grid(), which allowed us to import and manage our form records in a pre-built environment having security features enabled.

In this third, and final tutorial of the series, I would like to shed some light on how multiple web forms can exist on a single page, how a single form can submit data to multiple tables, and finally, a hint about modifying CSS of your web form (which is a common practice in classical PHP based web forms). The reason why I am going to this extent is just to ensure you that web forms in Web2Py are no second to PHP forms, and they have everything that a PHP form can offer – our forms require even less amount of coding, which is exactly the reason why Web2Py and other Pythonic web frameworks are getting popular.

Okay, let’s go.

1. Multiple Forms on a Single Page:

As the header suggests, we are going to integrate more than one web forms on a single page, arranged serially against each other. All these forms will be linked to different tables in the database, but will be incorporated and controlled using a single controller (in our case it is form_a()) function.

We already have one form in place, so we will define two more tables for two additional forms in our default.py:

db.define_table('registration',
    Field('firstname', requires=IS_NOT_EMPTY()),
    Field('lastname', requires=IS_NOT_EMPTY()),
    Field('gender', requires=IS_IN_SET(['Male', 'Female'])),
    Field('username', requires=IS_NOT_EMPTY()),
    Field('password', 'password'),
    Field('image', 'upload'))

db.define_table('personal',
    Field('nick_name', requires=IS_NOT_EMPTY()),
    Field('address', requires=IS_NOT_EMPTY()),
    Field('married', 'boolean'),
    Field('zip_code', requires=IS_NOT_EMPTY()))

Now we have two database tables named ‘registration’ and ‘personal’ having following fields:

registration:

  1. Firstname:
  2. Lastname:
  3. Gender (Drop-down):
  4. Username:
  5. Password:
  6. Image (Upload Field):

personal:

  1. Nickname:
  2. Address:
  3. Married (Check Box):
  4. Zip Code:

Once the database tables are defined, let’s work on our controller function to incorporate the two forms based on them:

def form_a():
   form1 = SQLFORM(db.registration, deletable=True, upload=URL(r=request, f='download'))
   if form1.accepts(request.vars, session):
       redirect(URL(r=request, f='form_a'))
       qq = db().select(db.registration.ALL)

   form2 = SQLFORM(db.personal, deletable=True, upload=URL(r=request, f='download'))
   if form2.accepts(request.vars, session):
       redirect(URL(r=request, f='form_a'))
       pp = db().select(db.personal.ALL)

   return dict(form1=form1, form2=form2)

Browse to see your work:

http://127.0.0.1:8000/forms/default/form_a/

You may have noticed this; I have taken out all those conditional notification messages from the controller function form_a(), which is just to show the minimal working of two forms at the same time. You can add those conditional statements or any other set of user functions any time you wish to. Now, let’s define them in the records() function to manage their records on a single admin page:

def records():
   records = SQLFORM.grid(db.registration, user_signature=False)
   recordsa = SQLFORM.grid(db.personal, user_signature=False)
   return locals()

2. Single Form Linked With Multiple Database Tables:

This one is a bit tricky. We are about to submit data from a single web form into two database tables (which is a usual thing in web forms), and for this, let us quickly define a new table named ‘professional’:

db.define_table('professional',
    Field('job_id', requires=IS_NOT_EMPTY()),
    Field('job_title', requires=IS_NOT_EMPTY()),
    Field('organization', requires=IS_NOT_EMPTY()),
    Field('email', requires=IS_NOT_EMPTY()),
    Field('supervisor_name', requires=IS_NOT_EMPTY()))

Following this, it is time to modify the form_a() controller to incorporate the second database table in the form:

def form_a():
    form=SQLFORM.factory(db.registration,db.professional, deletable=True, upload=URL(r=request, f='download'))
    if form.accepts(request.vars, session):
        reg = db.registration.insert(**db.registration._filter_fields(form.vars))
        form.vars.client=id
        prf = db.professional.insert(**db.professional._filter_fields(form.vars))
        redirect(URL(r=request, f='form_a'))
    return dict(form=form)

What is happening over here?

Well, we have modified the form_a() to act as a single web form linked with two database tables (namely ‘registration’ and ‘professional’). More specifically, the db.registration.insert() and db.professional.insert() methods are actually inserting the specific values associated with both database tables respectively. In this way, we ‘link-from’ the database tables (rather than linking-to) to insert the respective values of forms into different database tables. To view the records, modify the records() function as:

def records():
   records = SQLFORM.grid(db.registration, user_signature=False)
   recordsa = SQLFORM.grid(db.personal, user_signature=False)
   recordsp = SQLFORM.grid(db.professional, user_signature=False)
   return locals()

3. Modifying the Form’s Appearance:

No tricks in this one. Just login to your administrative panel (within your form application) and scroll down to the ‘Static files’ section to view all the CSS and layout files. You are free to modify and play with these files for changing the appearance of your web forms. Yes, you guessed it right: I am not going to get into the super-details of CSS form styling over here, but there is a good collection of CSS tips and tricks that you can use to play with your form’s front-end.

This is it. Hope you enjoyed our dive through different dimensions of web forms in Web2Py. Stay connected for more articles, tips, tricks and ideas about integrating secret Pythonic powers on web.

SHARE THIS POST
  • Stan

    you gave an interesting idea which feels refreshing to an old time php developer. lol. very informative article by the way.