Record deletion, keepvalues and field representation

May 2, 2010

Suppose you’ve 2 SQLFORMs to create/update records in a database table

def reprs(value):
    result  = A(value, _href=URL(r=request, f='index', args=value))
    return result

def index():
    keepvalues=True/False
    if not request.args:
        form = SQLFORM(db.my_table)
        if form.accepts(request.vars, session, keepvalues=keepvalues):
            response.flash  = T('record created')
    else:        
        form = SQLFORM(db.my_table, request.args(0), deletable=True)
        if form.accepts(request.vars, session):
            response.flash  = T('record created')
    db.my_table.id.represent = reprs
    records = db().select(db.my_table.ALL)
    return dict(form=form, records=records)
  • Now as you can see, we’ve some fun stuff :
    keepvalues when set to True when creating a record then the form will keep the values after successful creation of the new record and vice versa.
    keepvalues=True is very useful in successive insertion of similar data
  • In update forms, keepvalues is always set to True, even if you tried to set to False, it won’t work
    and this makes sense actually, you want to see the updated data after
    updating it.And any way this’s easily can be changed in the code in case you’ve another opinion.
  • The table_name.field_name.represent is cool as you can see, you can make the table you create contains a reference to update the record
    or to refer to another link [This depends on your needs]
  • In my opinion while the represent is a function that takes a string argument [field name], it would have been more useful if it could refer to the record as a whole, in this case you could make a field refer to a an action that may take as argument the value of another field.
    In the current situation you could do something like that by making a query based on the value of the field which is useless unless the field value is unique , so it’s more useful to be used with id fields in general.
    Moreover it could have taken the record, one will not be forced to make an extra query.
    Of course something like this can be done in other ways.
    If you’ve an argue about my point of view, let me know.
  • Another thing to notice is that when deleting a record, form variables should be cleared which is not the case here.
    In my openion this’s not a good idea in fact, and needs to be fixed because it’s really tempting to see the variables still in the form and makes one clicks the [‘submit’] button again to see what would happen
    and it returns ‘object not found’ error message
    One way to overcome this issue is to explicitly check whether user have asked to delete a record or not in the accepts() function.

    if form.accepts(request.vars, session):
        if form.vars.delete_this_record:
            #record is deleted then redirect user to the same page without  
              arguments [without the last argument if page takes many arguments]
            redirect(URL(r=request, f=....))
    

  • Restricting an exposed URL to either POST or GET

    April 17, 2010
  • forms usually use ‘POST’ by default
  • When you refresh a page that contains a form, then if you found that the page asks you for a confirmation to re-submit the form contents then you know that this’s a form that used ‘POST’ .
  • web2py forms usually use ‘POST’ too.
  • sometimes you need to restrict your actions[controller functions] to either POST/GET methods
  • in web2py you can do something like :

    def index():
        form = FORM(INPUT(_type='submit'), _method='GET')
        if form.accepts(request.get_vars,session):
            response.flash = T('form accepted')
        return dict(form=form)
    

    in your index.html, just do:

    {{=form}}
    
  • Now by submitting form, you get in URL something like :
    http://127.0.0.1/test/default/index?_formkey=43c71638-2dbe-4667-a07c-404999afb4c9&_formname=default
    
  • See the URL ‘this indicates that form is using GET’ since request variables are all sent in URL itself
  • in the form definition up there can you see the :
    _method='GET'
    
  • also when accepting the form we use :
    if form.accepts(request.get_vars)
    

    instead of:

    form.accepts(request.vars)
    
  • The same goes for POST, but it will be trivial to do such a thing since web2py forms usually use POST for submitting forms
  • In fact at any time , if you want to get the function used by a form, you can do
    form = SQLFORM(db.my_table)
    method=form.attributes['_method']
    
  • P.S
    You can use LiveHttpHeader firefox extension while doing your tests