Custom Display Values

65 views
Skip to first unread message

Gary

unread,
Jun 9, 2009, 12:06:11 PM6/9/09
to web2py Web Framework
I'm using crud to interact with a custom view.
form.custom.inpval.fieldname and form.custom.dspval.fieldname display
the proper value for most field types, but not files, select boxes and
checkboxes. The download easily fixes the file display, but I've been
unable to find a similar solution to displaying the 'lookup' value of
the select rather than the 'id' of the target? Ditto for the checkbox
rather that 'True/False'.

Thanks in advance for any help.

mdipierro

unread,
Jun 9, 2009, 12:38:40 PM6/9/09
to web2py Web Framework
with the new trunk you can do

{{=form.custom.widget.fieldname}}

Gary

unread,
Jun 9, 2009, 1:41:49 PM6/9/09
to web2py Web Framework
I tried {{=form.custom.widget.town_id}} in 1.63.5 and got an error
"AttributeError: 'NoneType' object has no attribute 'town_id'".
Using {{=form.custom.inpval.town_id}} returns a '1', the value of the
id in the 'Location' file pointing to the 'Town' file.

For clarification, does 'new trunk' mean something other than the
current release?

Thanks.

Fran

unread,
Jun 9, 2009, 2:00:37 PM6/9/09
to web2py Web Framework
On Jun 9, 6:41 pm, Gary <gary.k.ma...@gmail.com> wrote:
> For clarification, does 'new trunk' mean something other than the
> current release?

It means the live code downloaded via Bzr:
https://code.launchpad.net/~mdipierro/web2py/devel

So more current than the latest release.

F

mdipierro

unread,
Jun 9, 2009, 2:24:55 PM6/9/09
to web2py Web Framework
By trunk we mean "not officially released yet" and "not guaranteed to
work".

Massimo

Gary

unread,
Jun 9, 2009, 3:40:54 PM6/9/09
to web2py Web Framework
Thank you Fran and Massimo for the info.

I downloaded the trunk using:

bzr branch lp:~mdipierro/web2py/devel web2py-devel

and installed the application. The error message went away, but
{{=form.custom.widget.town_id}} still displayed '1' vs. the 'lookup'
value. It also didn't display a checkbox where indicated.

Appreciate the help.

Hans Donner

unread,
Jun 9, 2009, 3:51:02 PM6/9/09
to web...@googlegroups.com
Gary,
how dows your model look like?
And how does it show when you are just using SQLFORM?

Gary

unread,
Jun 9, 2009, 5:31:40 PM6/9/09
to web2py Web Framework
Hans,

The model is kind of long, but SQLFORM (I don't know how to only show
fields using SQLFORMS), as well as the Custom Update CRUD, works
fine. It's only the Read CRUD that is giving me a problem. In other
words, the input tag works fine but the field display is showing the
'id' value rather than the 'lookup' value.

Is this helpful or do you need more?

Thanks.

On Jun 9, 3:51 pm, Hans Donner <hans.don...@pobox.com> wrote:
> Gary,
> how dows your model look like?
> And how does it show when you are just using SQLFORM?
>

mdipierro

unread,
Jun 9, 2009, 6:47:57 PM6/9/09
to web2py Web Framework
Gary,
I need more explanation. One example or screenshot would help.

Massimo

Gary

unread,
Jun 9, 2009, 8:02:40 PM6/9/09
to web2py Web Framework
Massimo,

This is kind of complicated. It's part of a generalized application
that uses a database to to define which tables can be accessed through
CRUD. The database contains the table name, some search criteria and
decorators. The controllers look more like web2py source than a
"normal" controller. Here are the three main routines with a quick
explanation:

""""managetable() is called with a tablename, assures an action,
selects a response view, calls setsubmit() to write the requested crud
call and returns the dictionary value built in thefields(). """"

def managetable():
if request.args:
tablename = request.args[0]
id = request.args[1]
if request.args[1] == "0": session.action="create"
response.view = "%s/%s.html" % (request.controller, tablename)
form = eval(setsubmit(tablename))
return thefields(form)
if session.signon[session.searchfield]: managetable = eval
(session.signon[session.searchfield]+"(managetable)")

"""setsubmit() returns the crud command based on the session variable.
"""

def setsubmit(table):
if request.vars.submit1: session.action = "create"
if request.vars.submit2: session.action = "update"
if request.vars.submit3: session.action = "read"
if request.vars.submit4: session.action = "delete"
cmd = "crud."+session.action+"(db."+table
if session.action in ['read','update','delete']:
cmd += ",id)"
else:
cmd += ")"
return cmd

""" thefields() takes the components[0], extracts the fieldnames and
builds the crud dictionary to return."""

def thefields(curform):
mycomponents = curform.components[0]
mydict = dict(form=curform)
for mycount in range(len(mycomponents)):
mylabel = str(mycomponents[mycount][0])
mylabel = mylabel[mylabel.find('="')+2:mylabel.find('" ')]
mydict[mylabel]=mycomponents[mycount][1]
return mydict

===================
Here is an abbreviated Model:

db.define_table('menu',
db.Field('linkname','string',default='link_name'),
db.Field('linkactive','string',default='False'),
db.Field('linkcontroller','string',default='index'),
db.Field('tablefield','string',default='tablename.fieldname'),
db.Field('linkcondition','string',length=64,default='True'),
db.Field
('tabledecorator','string',length=64,default='auth.requires_login()'),
db.Field('tablematch','string',length=64,default='id'))

db.define_table('town',
db.Field('townname','string'),
db.Field('towncode','string'))
##
db.define_table('location',
db.Field('poleno','string'),
db.Field('town_id',db.town))
##
db.town.townname.requires=[IS_NOT_EMPTY(),IS_NOT_IN_DB
(db,'town.townname')]
db.town.towncode.requires=[IS_NOT_EMPTY(),IS_NOT_IN_DB
(db,'town.towncode')]

db.location.poleno.requires=[IS_NOT_EMPTY(),IS_NOT_IN_DB
(db,'location.poleno')]
db.location.town_id.requires=IS_IN_DB(db,db.town.id ,'%(townname)s')

===================
Here is a portion of a custom view using the generated fields:

{{extend 'layout.html'}}
<h1>location
{{if session.action == "update":}}
Update
{{elif session.action == "create":}}
Add
{{pass}}
</h1>
<form action="" enctype="multipart/form-data" method="post">
<table>
<tr id=location_poleno__row>
<td><label for="location_poleno" id="location_poleno__label">Poleno:
</label></td>
{{if session.action in ["update","create"]:}}
{{=location_poleno}}
{{else:}}
<td>{{=form.custom.inpval.poleno}}</td>
{{pass}}
<td></td>
</tr>
<tr id=location_town_id__row>
<td><label for="location_town_id" id="location_town_id__label">Town
Id: </label></td>
{{if session.action in ["update","create"]:}}
{{=location_town_id}}
{{else:}}
<!-- THIS IS THE LINE THAT SHOULD RETURN A SELECTED FIELD FROM A
SELECT TAG -->
<td>{{=form.custom.widget.town_id}}</td>
{{pass}}
<td></td>
</tr>
.............

See the forth line from the bottom. (Caps for emphasis, not yelling).
Two lines above that, {{=location_town_id}} produces a dropdown
<select> field that works perfectly in crud, including errors. For
reference, this all started in thread:
http://groups.google.com/group/web2py/browse_thread/thread/5ff39195cb22d810/46792d84246385dd?q=crud+validation&lnk=ol&
I'm including this reference just in case it help to have the
background.

I'd be glad to send you the entire application if that helps. Just
let me know.

Much thanks!

mdipierro

unread,
Jun 9, 2009, 11:34:58 PM6/9/09
to web2py Web Framework
Allow me simplify it, else I do not understand it:

def managetable():
        (tablename, id) = (request.args(0), request.args(1)) # can be
None
    response.view = "%s/%s.html" % (request.controller,
tablename)
    return thefields(setsubmit(tablename))
# why not return dict(form=setsubmit(tablename)) ?

# this I do not understand
# if session.signon[session.searchfield]: managetable = eval
# (session.signon[session.searchfield]+"(managetable)")

def setsubmit(tablename,record=None):
    if request.vars.submit1: command="create"
elif request.vars.submit2: command="read"
elif request.vars.submit3: command="update"
elif request.vars.submit4: command="delete"
return getattr(crud,command)(db[tablename],record)

def thefields(curform):
mydict(form=curform)
for fieldname in curform.record:
if fieldname in curform.custom.widget:
mydict[fieldname] = curform.custom.widget[fieldname]
return mydict

{{extend 'layout.html'}}
{{action = request.args(0)}}
<h1>location
{{if action == "update":}} Update
{{elif action == "create":}} Add
{{pass}}
</h1>
<form action="" enctype="multipart/form-data" method="post">
<table>
<tr id="location_poleno__row">
<td><label for="location_poleno" id="location_poleno__label">Poleno:
</label></td>
  {{if action in ["update","create"]:}}
    {{=" *** location_poleno"}}
  {{else:}}
    <td>{{=form.custom.widget.poleno}}</td>
  {{pass}}
  <td></td>
</tr>
<tr id="location_town_id__row">
>   <td><label for="location_town_id" id="location_town_id__label">Town
Id: </label></td>
  {{if action in ["update","create"]:}}
    {{=" *** location_town_id"}}
  {{else:}}
<!-- THIS IS THE LINE THAT SHOULD RETURN A SELECTED FIELD FROM A
SELECT TAG -->
    <td>{{=form.custom.widget.town_id}}</td>
  {{pass}}
  <td></td>
</tr>

Does this work as expected? I do not underatnd it well enough to
debug. sorry.

Massimo

Gary

unread,
Jun 10, 2009, 4:49:17 PM6/10/09
to web2py Web Framework
Massimo,

Thank you so much for your feedback. Most of the changes you
suggested certainly made the code simpler and easier to read, but I
have a couple of issues that I don't understand.

1) It appears that the line:

getattr(crud,session.action)(db[tablename],record)

executes the crud call, but I don't understand how getattr() does
that. Could you provide a brief explanation?

2) If I directly return the dictionary that results from setsubmit
(tablename), what would the format of the return be and what should
the variables in the form be named? I tried a couple of combinations
(widgets, inpval, dspval) , but they all failed (widget) carried extra
data (impval) or failed to display an <input> on update.

3) In thefields(), the value of curform is:

<form action="" enctype="multipart/form-data" method="post"><table><tr
id="location_poleno__row"><td><label for="location_poleno"
id="location_poleno__label">Poleno: </label></td><td>EBW 1234</
td><td></td></tr><tr id="location_town_id__row"><td><label
for="location_town_id" id="location_town_id__label">Town Id: </label></
td><td>1</td><td></td></tr> .....

and curform.record is:

<SQLStorage {'electricprovider': None, 'update_record': <function
<lambda> at 0x9ff80d4>, 'npolesize': None, 'notifydate':
datetime.datetime(2009, 3, 27, 8, 9, 43), 'id': 2,
'specialprotection': None, 'city': 'East Brunswick', 'data1': None,
'zipcode': '08816', 'cableprovider': None, 'state': 'NJ', 'town_id':
1, ....

Please notice that in both places, the value of town_id is 1 and not
the value in the related table.

When I set mydict = dict(form=curform) is was able to fix a syntax
error 'mydict does not exist' but I'm not sure that's the right thing
to do. However, the real problem is an error message that says
curform.custom.widget is not iterable. Even if it fixes it, I'm still
not sure what the variables in the form should be named.

It seems that the original code that was generated using components[0]
accomplished everything except providing the current values of
'lookup' fields in display mode. When used for add or update, they
worked as expected - including error messages. I assume that the
custom fields are meant to provide the same functionality, but I must
be using them incorrectly.

You help is greatly appreciated.

mdipierro

unread,
Jun 10, 2009, 5:59:21 PM6/10/09
to web2py Web Framework
On Jun 10, 3:49 pm, Gary <gary.k.ma...@gmail.com> wrote:
> Massimo,
>
> Thank you so much for your feedback.  Most of the changes you
> suggested certainly made the code simpler and easier to read, but I
> have a couple of issues that I don't understand.
>
> 1) It appears that the line:
>
> getattr(crud,session.action)(db[tablename],record)

getattr(yyy,'xxx') is the same as yyy.xxx

> executes the crud call, but I don't understand how getattr() does
> that.  Could you provide a brief explanation?
>
> 2) If I directly return the dictionary that results from setsubmit
> (tablename), what would the format of the return be and what should
> the  variables in the form be named?  I tried a couple of combinations
> (widgets, inpval, dspval) , but they all failed (widget) carried extra
> data (impval) or failed to display an <input> on update.

You only need widgets

<form>
{{=form.custom.widget.field1}}
{{=form.custom.widget.field2}}
{{=form.custom.widget.field3}}
<input type="submit">
{{=form.hidden_fields()}}
</form>

> 3) In thefields(), the value of curform is:
>
> <form action="" enctype="multipart/form-data" method="post"><table><tr
> id="location_poleno__row"><td><label for="location_poleno"
> id="location_poleno__label">Poleno: </label></td><td>EBW 1234</
> td><td></td></tr><tr id="location_town_id__row"><td><label
> for="location_town_id" id="location_town_id__label">Town Id: </label></
> td><td>1</td><td></td></tr> .....
>
> and curform.record is:
>
> <SQLStorage {'electricprovider': None, 'update_record': <function
> <lambda> at 0x9ff80d4>, 'npolesize': None, 'notifydate':
> datetime.datetime(2009, 3, 27, 8, 9, 43), 'id': 2,
> 'specialprotection': None, 'city': 'East Brunswick', 'data1': None,
> 'zipcode': '08816', 'cableprovider': None, 'state': 'NJ', 'town_id':
> 1,  ....
>
> Please notice that in both places, the value of town_id is 1 and not
> the value in the related table.
>
> When I set mydict =  dict(form=curform) is was able to fix a syntax
> error 'mydict does not exist' but I'm not sure that's the right thing
> to do.  However, the real problem is an error message that says
> curform.custom.widget is not iterable.  Even if it fixes it, I'm still
> not sure what the variables in the form should be named.

I think you can do:

{{for fieldname in form.custom.widget:}}
<label>{{=form.custom.labels[fieldname]}}</label>{{=form.custom.widget
[fieldname]}}
{{pass}}

I do not think you need thefields since it only provides info that is
alredy in the form.

Not sure if this helps.

Gary

unread,
Jun 10, 2009, 9:58:59 PM6/10/09
to web2py Web Framework
Massimo,

Thank you. You mentioned before that widget worked in the trunk - you
are, of course correct, but I just wanted to make note to others that
it fails in the current version 1.63.5. Also, {{=form.custom.labels
[fieldname]}} did not work in the trunk. It failed with "TypeError:
'NoneType' object is unsubscriptable". Just wanted you to know.

Thanks again!

Gary

unread,
Jun 10, 2009, 10:28:06 PM6/10/09
to web2py Web Framework
Massimo,

I was so excited that the 'widget' worked that I failed to notice that
I have the same problem that I started with - except the code is much
cleaner. :-)

When the crud read is executed, the valued returned is the value in
the table. While this is fine for most fields, when the field is
defined as an 'id' to another table, for example:

db.location.town_id.requires=IS_IN_DB(db,db.town.id ,'%(townname)s')

the widget and SQLFORM displays the update/create field as a
<select><options> with a value selected. So, on the update/create,
the screen shows a pre-selected dropdown box with a town name, but on
read, only the number representing the id is displayed. Can the
widget for read be configured to display the selected value as text
and check boxes (rather than True/False)?

Thanks.

mdipierro

unread,
Jun 10, 2009, 10:36:46 PM6/10/09
to web2py Web Framework
Now I understand the problem better. No problem.

widget is always an input widget. Output widgets are called
"represent" and usually much simpler. This will do what you want:

db.location.town_id.represent=lambda id: SPAN(db.town[id].townname)

Massimo

Hans Donner

unread,
Jun 11, 2009, 12:27:24 AM6/11/09
to web...@googlegroups.com
> You only need widgets
>
> <form>
> {{=form.custom.widget.field1}}
> {{=form.custom.widget.field2}}
> {{=form.custom.widget.field3}}
> <input type="submit">
> {{=form.hidden_fields()}}
> </form>

better is to use {{=form.start}} in stead of <form>, this will take
over any actions/methods etc that are used in the SQLFORM,
and for now {{=form.close}} and </form> are the same unless I can
figure out how to include the {{=form.hidden_fields()}} properly in
{{=form.close}}

mdipierro

unread,
Jun 11, 2009, 1:12:06 AM6/11/09
to web2py Web Framework
done but it is now

{{=form.custom.form.begin}}
{{=form.custom.widget.field1}}
{{=form.custom.widget.field2}}
{{=form.custom.widget.field3}}
<input type="submit">
{{=form.custom.form.end}} includes hidden fields!

Massimo

Horst Herb

unread,
Jun 11, 2009, 1:28:00 AM6/11/09
to web...@googlegroups.com
On Thu, Jun 11, 2009 at 3:12 PM, mdipierro<mdip...@cs.depaul.edu> wrote:
>
> done but it is now
>
> {{=form.custom.form.begin}}
> {{=form.custom.widget.field1}}
> {{=form.custom.widget.field2}}
> {{=form.custom.widget.field3}}
> <input type="submit">
> {{=form.custom.form.end}} includes hidden fields!

Fantastic! That's easy and intuitive and yet so flexible and powerful.

Thanks - this is really getting somewhere now.

Horst

Hans Donner

unread,
Jun 11, 2009, 1:29:20 AM6/11/09
to web...@googlegroups.com
Nice,

> <input type="submit">

can be done with
{{=form.custom.submit}}

and if you want to add the delete? checkbox
{{=form.custom.deletable}}

Gary

unread,
Jun 11, 2009, 8:27:10 AM6/11/09
to web2py Web Framework
Correction. {{=form.custom.labels[fieldname]}} did work in the trunk,
but the proper syntax is "label", not "labels".

Sorry for the misinformation.

mdipierro

unread,
Jun 11, 2009, 8:28:08 AM6/11/09
to web2py Web Framework
I am changing "form.begin" ot just "begin" as below:

{{=form.custom.begin}}
{{=form.custom.widget.field1}}
{{=form.custom.widget.field2}}
{{=form.custom.widget.field3}}
{{=form.custom.submit}}
{{=form.custom.end}}

On Jun 11, 12:29 am, Hans Donner <hans.don...@pobox.com> wrote:
> Nice,
>
> > <input type="submit">
>
> can be done with
> {{=form.custom.submit}}
>
> and if you want to add the delete? checkbox
> {{=form.custom.deletable}}
>
Reply all
Reply to author
Forward
0 new messages