Question

I am using web2py and am puzzled by how to use the represent attribute in my database field definition.

I have the following two table definitions:

my_info = db.define_table('my_info',
    Field('my_uuid', 'string', length=64, requires=[IS_NOT_EMPTY()], unique=True),
    Field('my_name', 'string', length=512, requires=[IS_NOT_EMPTY()]),
    Field('my_type', 'string', length=32, requires=[IS_NOT_EMPTY()]),
)

my_other_info = db.define_table('my_other_info',
    Field('my_other_uuid', 'string', length=64, requires=[IS_NOT_EMPTY()], unique=True),
    Field('my_info_id', 'reference my_info', requires=IS_IN_DB(db, db.my_info.my_uuid, '')),
    Field('my_other_name', 'string', length=512, requires=[IS_NOT_EMPTY()]),
    Field('my_other_type', 'string', length=32, requires=[IS_NOT_EMPTY()]),
)

It would help if I could get the value of my_uuid whenever I access the my_info_id field in the my_other_info table.

I tried something like:

represent=lambda id, row: db(db.my_info.id==row.my_info_id).select(db.my_info.my_uuid).first().as_dict()['my_uuid']

But this does not seem to be working for me and I think there is some major gap in my knowledge as to how I should go about this.

Please note that there is no form processing or any frontend processing involved in this application and I would like to use the represent attribute to cut down on DB queries in my REST API.

In addition the REST API is going to be accessed using a command line interface.

I hope someone can give me some pointers on getting represent to work.

Thanks, nav

Was it helpful?

Solution

Your "represent" function is correct, though the .as_dict() is unnecessary, and it can be further simplified as follows:

represent=lambda id, row: db.my_info(id).my_uuid

However, keep in mind that the "represent" attribute is only used when web2py displays data via SQLTABLE, SQLFORM.grid, and read-only SQLFORM edit forms. If you want to have the "represent" transformation applied in other contexts, you have to do so explicitly. One option is to use the Rows.render() method:

rows = db(db.my_other_info).select()
my_uuid = rows.render(0).my_info_id

The .render() method of a Rows object takes an index and returns that record with all of the "represent" attributes applied to its fields. If no index is supplied, it instead returns an iterator so you can loop over the records. If you don't want to convert all the fields, you can optionally supply a fields argument, which is a list of fields to convert.

Also, note that your IS_IN_DB validator is incorrect. Because the my_info_id field is storing record IDs of the db.my_info table, it should be IS_IN_DB(db, db.my_info.id). Actually, to make things easier, you can just do:

my_info = db.define_table('my_info',
    Field('my_uuid', 'string', length=64, requires=[IS_NOT_EMPTY()], unique=True),
    ...,
    format='%(my_uuid)s')

my_other_info = db.define_table('my_other_info',
    Field('my_other_uuid', 'string', length=64, requires=[IS_NOT_EMPTY()], unique=True),
    Field('my_info_id', 'reference my_info'),
    ...)

When you define a reference field that references a table with a "format" attribute, the "format" attribute of the referenced table is used to generate a default IS_IN_DB validator and a default "represent" attribute for the reference field.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top