I want to form a SQLFORM.grid() of a user requested table. Basically so that the user can change which table they want to view. This is what I've come up with so far:
The action. It initializes the grid
to None
, unless something else is requested:
def sheet():
grid = None
dbTables = db.tables
if request.args:
table = request.args(0,cast=str)
grid = SQLFORM.grid(db[table])
return dict(grid=grid, dbTables=dbTables)
The view. It shows a requested table, if one was requested:
{{extend 'layout.html'}}
{{if grid == None:}}
No table selected
{{else:}}
{{=grid}}
{{pass}}
Now this does work if nothing is requested, but if I type into address bar, say, /sheet/auth_user
or anything else, it shows me a flash message that says "not authorized" and writes a wierd signature into the address bar: /sheet?_signature=69abba0414d5920e970d8c9b17f5cbb60a5bbecc
.
The only thing that breaks this, is the request. If I strip the code down to basics and change the table I want manually in the code, it works just fine. So this works:
def sheet():
grid = None
dbTables = db.tables
table = "auth_user"
grid = SQLFORM.grid(db[table])
return dict(grid=grid, dbTables=dbTables)
What am I doing wrong?
The grid uses the URL args (everything in the URL path after the controller and function names) for routing to its built-in functionality (e.g., to view/create/update records). So, if you want to include some URL args in the base URL that are to be ignored by the grid, you have to specify those args via its args
argument:
grid = SQLFORM.grid(db[table], args=[table])
The above tells the grid to ignore the first arg in the URL (and to retain it when generating its own internal URLs).
If you fail to specify the args
as above, not only will the built-in functionality fail, but when user_signature=True
(which is the default), access will be denied because the base URL of the function does not match the requested URL (which includes an unknown URL arg). That is why you received the "not authorized" message. If you disable the user_signature
(not recommended), you would not receive the "not authorized" message, but none of the internal grid links would work properly (because the first URL arg would get dropped, thereby eliminating the reference to the proper table).
Also, note that your function can be simplified:
def sheet():
table = request.args(0)
grid = SQLFORM.grid(db[table], args=[table]) if table in db.tables else None
return dict(grid=grid)
Also, in the view, just do:
{{=grid or 'No table selected'}}