From bit to a heart beat

insane innovations from a sane insanity

Sat Dec 26

Implementing a Rails-like scaffolding in web2py (but better!)

Sometimes I want to create a better administration panel for our clients. With this hack you can create an add/edit/delete panel for every table you like and extend it easily. in order to use it you just go inside the controllers and add:

@scaffold(None)
def authors():
pass

this will create an admin page (authors) that has all the properties from the table “authors”. if you have to “admin” a different table just put it’s name:

@scaffold("other_table")
def authors():
pass

Read the comments for more hacks. PS: I have also a new version that you can pass custom queries (I’ll keep you updated). PS2: Also a version with DataTables (http://datatables.net/)

You can also chain decorators in order to prevent unauthorized access:

@auth.requires_login()
@scaffold("other_table")
def authors():
pass

Now, the installation:

First, put this code inside a module (or in a separate file in models).

def scaffold(tblname=None, fieldid=None): “”” Decorator that exposes show/add/edit/delete for admin purposes

    You can specify a table name else it will use the
name of the function as table name
You can specify a field id that will be displayed for the record
else it will use the first field value
"""

def decorator_outside(func):

def decorator_inside(*args):

db_name = db # we could get the database name from globals
table_name = func.__name__ if tbl_name == None else tbl_name
if table_name not in db_name.tables:
raise Exception("No table with name '%s' found" % table_name)

form = None
if len(request.args) > 1:
action = request.args[0]
record_id = request.args[1]

if action == 'create':
form = crud.create(db_name[table_name])

elif action == 'show':
form = crud.read(db_name[table_name], record_id)

elif action == 'edit':
form = crud.update(db_name[table_name], record_id)

elif request.args[0] == 'delete':
form = crud.delete(db_name[table_name], record_id)

result = db_name(db_name[table_name].id > 0).select()
func()

return dict(rows=result, cntr_name=table_name, form=form, field_id=field_id)
return decorator_inside

return decorator_outside

The do the action in the controller @scaffold(“other_table”) def authors(): pass

Finally create a view file:

{{extend 'layout.html'}}
{{ include 'scaffold.html' }}

and paste this into your views folder:

{{= form if form != None else "" }}
<br />
<table>
{{ i = 0 }}
{{ for row in rows: }}
{{ i += 1 }}
<tr class="{{='even' if i%2 else 'odd'}}">
<td class='main'><a href="{{= URL(r=request, f=cntr_name+'/show',
args=row.id) }}">{{= row.values()[field_id] }}</a></td>
<td><a href="{{= URL(r=request, f=cntr_name+'/edit',
args=row.id) }}">Edit</a></td>
<td><a href="{{= URL(r=request, f=cntr_name+'/delete',
args=row.id) }}">Delete</a></td>
</tr>
{{ pass }}
</table>

{{ if not len(rows): }}
No records found
{{ pass }}

<br />
<a href="{{= URL(r=request, f=cntr_name+'/create/new') }}">Add new</a>
Comments (View)
blog comments powered by Disqus