How to catch index error

48 views
Skip to first unread message

Maurice Waka

unread,
Mar 19, 2019, 2:57:35 PM3/19/19
to web2py-users
I have a code that works OK except when there is no data in the database.
Here is the code, using MongoDB.
model code:

db.define_table('sleep',
                Field('awake','double',default=0),
                Field('light_sleep','double',default=0),
                Field('deep_sleep','double',default=0),
                Field('author', 'reference auth_user', default=auth.user_id, readable=False, writable=False),
                common_filter = lambda query: db.sleep.author == auth.user_id)

def sleep_chart():
    response.files.append(URL('e_default','static/js/pygal-tooltips.min.js'))
    response.headers['Content-Type']='image/svg+xml'
    custom_style = Style(
        background='transparent',
        plot_background='transparent',
        foreground='#53E89B',
        foreground_strong='#53A0E8',
        foreground_subtle='#630C0D',
        opacity='.6',
        opacity_hover='.9',
        transition='400ms ease-in',
        colors=('#E853A0', '#E8537A', '#E95355', '#E87653', '#E89B53')
        )
    data = db(db.sleep).select()
    gauge = pygal.SolidGauge(inner_radius=0.70)
    percent_formatter = lambda x: '{:.10g}Hrs'.format(x)
    gauge.value_formatter = percent_formatter

    gauge.add('Awake', [{'value':[i.awake for i in data][-1], 'max_value': 24}])
    gauge.add('Light Sleep', [{'value':[i.light_sleep for i in data][-1], 'max_value': 24}])
    gauge.add('Deep Sleep', [{'value':[i.deep_sleep for i in data][-1], 'max_value': 24}])
    return gauge.render()

def mySleep():
    chart= URL('default', 'sleep_chart')
    form = SQLFORM(db.sleep, submit_button=T('Submit')).process()
    return dict(chart = chart,form=form)

Here is the problem:

When a new user registers into the system, by default, there is no data recorded in the database, so I get the error(see attached) below.

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
 
Traceback (most recent call last):
 
File "/home/mau/web2py/gluon/restricted.py", line 219, in restricted
 
exec(ccode, environment)
 
File "/home/mau/web2py/applications/Hesty/controllers/e_default.py", line 708, in <module>
 
File "/home/mau/web2py/gluon/globals.py", line 421, in <lambda>
 
self._caller = lambda f: f()
 
File "/home/mau/web2py/gluon/tools.py", line 3868, in f
 
return action(*a, **b)
 
File "/home/mau/web2py/applications/Hesty/controllers/e_default.py", line 649, in sleep_chart
 gauge
.add('Awake', [{'value':[i.awake for i in data][-1], 'max_value': 24}])
IndexError: list index out of range


Expectation:I want to have a default figure in the database. I have tried having "default=0" but the int only appears in the form text area. So the error persists.
Is there a way to have a default figure in the database or a way to catch this errors and let the new user to input int figure?

Screenshot from 2019-03-19 21-40-34.png

isi_jca

unread,
Mar 19, 2019, 4:55:43 PM3/19/19
to web...@googlegroups.com
def sleep_chart():
    response.files.append(URL('e_default','static/js/pygal-tooltips.min.js'))
    response.headers['Content-Type']='image/svg+xml'
    custom_style = Style(
        background='transparent',
        plot_background='transparent',
        foreground='#53E89B',
        foreground_strong='#53A0E8',
        foreground_subtle='#630C0D',
        opacity='.6',
        opacity_hover='.9',
        transition='400ms ease-in',
        colors=('#E853A0', '#E8537A', '#E95355', '#E87653', '#E89B53')
        )
    data = db(db.sleep).select()
    gauge = pygal.SolidGauge(inner_radius=0.70)
    percent_formatter = lambda x: '{:.10g}Hrs'.format(x)
    gauge.value_formatter = percent_formatter

    # check if the select retrieve data
    if data:
         gauge.add('Awake', [{'value':[i.awake for i in data][-1], 'max_value': 24}])
         gauge.add('Light Sleep', [{'value':[i.light_sleep for i in data][-1], 'max_value': 24}])
         gauge.add('Deep Sleep', [{'value':[i.deep_sleep for i in data][-1], 'max_value': 24}])
    else:
         gauge.add('Awake', [{'value':0, 'max_value': 24}])
         gauge.add('Light Sleep', [{'value':0, 'max_value': 24}])
         gauge.add('Deep Sleep', [{'value':0, 'max_value': 24}])

    return gauge.render()

Dave S

unread,
Mar 19, 2019, 4:58:11 PM3/19/19
to web2py-users


On Tuesday, March 19, 2019 at 11:57:35 AM UTC-7, Maurice Waka wrote:
I have a code that works OK except when there is no data in the database.

[...]
    gauge.add('Awake', [{'value':[i.awake for i in data][-1], 'max_value': 24}])
    gauge.add('Light Sleep', [{'value':[i.light_sleep for i in data][-1], 'max_value': 24}])
    gauge.add('Deep Sleep', [{'value':[i.deep_sleep for i in data][-1], 'max_value': 24}])
    return gauge.render()

[...]
 File "/home/mau/web2py/applications/Hesty/controllers/e_default.py", line 649, in sleep_chart
 gauge.add('Awake', [{'value':[i.awake for i in data][-1], 'max_value': 24}])
IndexError: list index out of range


Expectation:I want to have a default figure in the database. I have tried having "default=0" but the int only appears in the form text area. So the error persists.
Is there a way to have a default figure in the database or a way to catch this errors and let the new user to input int figure?

The simplistic way is to wrap the lines I left in the quoted material:

if len(data):

    gauge
.add('Awake', [{'value':[i.awake for i in data][-1], 'max_value': 24}])
    gauge
.add('Light Sleep', [{'value':[i.light_sleep for i in data][-1], 'max_value': 24}])
    gauge
.add('Deep Sleep', [{'value':[i.deep_sleep for i in data][-1], 'max_value': 24}])
else:
    gauge
.add('Unknown', [{'value':[0], 'max_value': 24}])

A better person than I might put the if into the comprehension, but I tend not to get that right.

/dps

Leonel Câmara

unread,
Mar 19, 2019, 8:45:42 PM3/19/19
to web2py-users
Notice that, it seems you are using [-1] because want to get the last record where the user was awake/light sleep/sleep, however you don't use an order by, so depending on the strategy the database decides to use, there's no guarantee that it will be the last. This is also inefficient because you only want the last record and you're getting all the records and they could be hundreds in the future.

Couldn't you just do:

    last_sleep = db(db.sleep.id > 0).select(orderby=~db.sleep.id, limitby=(0,1)).first()
    gauge.add('Awake', [{'value':last_sleep.awake if last_sleep else 0, 'max_value': 24}])
    gauge.add('Light Sleep', [{'value':last_sleep.light_sleep if last_sleep else 0, 'max_value': 24}])
    gauge.add('Deep Sleep', [{'value':last_sleep.deep_sleep if last_sleep else 0, 'max_value': 24}])

Maurice Waka

unread,
Mar 20, 2019, 2:48:32 AM3/20/19
to web...@googlegroups.com
This works well Boss!!
Thanks a lot and God Bless!
Regards

--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to a topic in the Google Groups "web2py-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/web2py/9mI7-ZkpA_0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to web2py+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Dave S

unread,
Mar 21, 2019, 3:56:35 PM3/21/19
to web2py-users


On Tuesday, March 19, 2019 at 5:45:42 PM UTC-7, Leonel Câmara wrote:
Notice that, it seems you are using [-1] because

I thought he was doing that to test our ability to count brackets, braces, and parens.  (GG's default font, as used on my screen, makes them very close in appearance; using the code wrapper helps by monospacing.)
 

and there you see an example of what I have a hard time doing right ... conditionals in comprehensions.

/dps
 
Reply all
Reply to author
Forward
0 new messages