Setting a form field default value

  • Many times and in certain situations , one needs to set a default (certain) value for a form filed

    suppose you’ve :

  • #in model:
    db.define_table('my_table', Field('my_field', 'string'))
    
    #in controller:
    form = SQLFORM(db.my_table)
    
    if form.accepts(...):
       print form.vars.my_table
    
  • Now I want the ‘my_filed’ to have a default value, may be : ‘Hamdy’
    what should I do ?
  • In fact you should differentiate between 3 suitations:
    • you need the form always to display and accept ‘Hamdy’ as a default value if user didn’t enter his custom text.
      This can be achieved by :

      db.define_table('my_table', Field('my_field', 'string', default='Hamdy'))
      

      or:

      form.vars.my_field.default = 'Hamdy'  # b4 defining the form
      form = SQLFORM(db.my_table)
      
      if form.accepts(...):
         print form.vars.my_table
      
    • The second situation is that the default string is variable depending on some conditions in this case, one should always use :
    • form.vars.my_field.default = 'Hamdy'  # b4 defining the form
      form = SQLFORM(db.my_table)
      

      which is suitable for almost all conditions

    • The 3rd situation is when you have a classic form, may be using :
      form = FORM()
      

      you can use Field(”), default=….) in it but what if the default value is variable ?
      you can’t set the value using db. …… since the form is not dealing with a database table so what can you do ?

      In this case make something like :

      form = FORM()
      form.vars.field = 'Hamdy'  # after the definition of the form
      if form.accepts(..., ...):
        # do something
      

      This technique is also very useful for SQLFORM that is dealing with a database table but in a certain situation you added to it an additional field (field added to form not to db table).
      In this case you can still play with it using this method.

  • To this extent, I guess you’re almost get how to deal efficiently with web2py forms, but I still have more 🙂
    One another interesting problem arises when you set in your model a field to be readable=False, writable=False and this’s a common situation when using a timestamp (creation_time) field in youer database table, in such a case you do something like :

    db.define_table('my_table', Field(...), Field('timestamp', 'datetime', readable=False, writable=False, default=request.now))
    
  • Now when ever trying to make a SQLFORM out of this table, user will not see the timestamp field , it will be updated though when submitting data.
    In fact readable=False, writable=False prevents this field to be a prt of the form.
    So having in my model :

    db.define_table('toto', Field('lolo'), Field('soso', readable=False, writable=False, default='hamdy'))
    

    and in my controller :

    def index():
    
        form = SQLFORM(db.toto)
        if form.accepts(request.vars, session):
            print form.vars
            form.vars.lolo = 'yet another value'   # -> not working
            response.flash = T('form accepted')
        return dict(form=form)
    
  • user will see one field ‘lolo’ and when trying to print the form.vars upon accepting it, you’ll find no existence for the ‘soso’ field
  • trying to set this a value for this field upon accepting the form using

    form.vars.lolo = 'yet another value' will not work also
    

    database will have the default value which is ‘Hamdy’ for this field for every new record you try to create.

  • what is going to work is to set the default value before defining the form at the database level not on the form level , Since form doesn’t really include this particular field :
      db.toto.soso.default = 'Another value'   #working
      form = SQLFORM(db.toto)
    
  • At this level there’s still no problem, the problem in fact will appear whenever you try to make additional check on this particular field value
    upon accepting the form.
    Say for example you made :

      db.toto.soso.default = session.name  #working
      form = SQLFORM(db.toto)
    
  • Now suppose you want to make additional check for this session.name variable to make sure it’s not just a garbage.
    In such situations you may use the onvalidation function while accepting the SQLFORM form so that more validation can be done

    def check(form):
        if form.vars.soso == 'Not hamdy':
            print 'Not hamdy'
            form.vars.soso = 'Not Not Not hamdy'
    
    def index():
        db.toto.soso.default = 'Not hamdy'   #working
        form = SQLFORM(db.toto)
        if form.accepts(request.vars, session, onvalidation=check):
            response.flash = T('form accepted')
        return dict(form=form)
    
  • Now as you see check() function is evaluated but does nothing since there’s no existence for a form.vars.soso since the field itself is not a part of the form

    SO what to do?

    It’s simple , in the definition of SQLFORM you can choose what fields you want in the form
    so you simply do something like:

    def check(form):
        if form.vars.soso == 'Not hamdy':
            form.errors['lolo'] = "There's an error"
                    
    def index():
        db.toto.soso.default = 'Not hamdy'   #working
        form = SQLFORM(db.toto)
        form.vars.soso = 'Not hamdy'  # it's a python magic
        if form.accepts(request.vars, session, onvalidation=check):
            response.flash = T('form accepted')
        return dict(form=form)
    
    

    form.vars.soso = ‘Not hamdy’ is just a python magic, being able to create and set an object attribute on the fly and it really just a variable
    not related to the form .
    we just created it to check the value.

  • The last problem that may face a user is that he/she may have to display this field in some certain situations but in others it should be hidden.
    Now it’s time for a user to decide what is the default case should it be hidden or shown by default.
    If it’s hidden by default you can show it in SQLFORM by using

     form = SQLFORM(db.toto, fields=['lolo', 'soso'])
    

    By using fields=[] you can choose what fields to display

    and if the the other case is the default, you can hide the field using

    db.soso.readable = False
    db.soso.writable = False
    form = SQLFORM(db.toto)
    
  • Advertisements

    One Response to Setting a form field default value

    1. Joe says:

      Hi,

      Good stuff you covered here that helped me out!

      Thanks

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s

    %d bloggers like this: