Forums

web2py - refreshing python script on page refresh

Hi, I'm very new to python and web2py so possibly not using the correct language to describe what I'm after but here goes...

In my web2py app I have a python module that generates a random quote from a Google spreadsheet (using gspread). I've managed to get so far as displaying the random quote in my web2py app. I've added in an html 'refresh' button to the page, but when I refresh the page the quote stays the same. How do I make the python script run again each time I refresh the page?

I have tried adding session.forget(response) to the default.py controller but this doesn't seem to have done anything.

I also tried adding from gluon.custom_import import track_changes; track_changes(True) to the db.py model and this doesn't seem to have done anything either.

I'm not quite sure why you need to store the quote in the session at all - surely you can just fetch it and put it in the response page without storing it anywhere? That will ensure it will change every time the page is being refreshed, provided your browser isn't caching it.

+1 to what Cartroo says, that sounds like the right way to do it -- unless we're missing something...?

I don't know if it's being stored or not. I don't really get how it works! It seems like it's being cached or stored and I want to stop this from happening so that a new quote is shown on page refresh. What code do I put where?

Perhaps it would help if we looked at your code -- could you point us at the URL where the quote appears? And can I look at the source code in your account? Or perhaps you could post the code here?

So my module is this:

import gspread
import random

gc = gspread.login('username','password')
sh = gc.open_by_key('spreadsheet_key')
worksheet = sh.sheet1

values_list = worksheet.col_values(2)
range_end = len(values_list)

random_number = random.randint(2, range_end)

while worksheet.cell(random_number, 5).value != "yes" :
    random_number = random.randint(2, range_end)

who_said_it = worksheet.cell(random_number, 2).value
about_what = worksheet.cell(random_number, 3).value
quote = worksheet.cell(random_number, 4).value

Then in default.py controller I have:

def quote():
    import quote
    return dict(who_said_it = quote.who_said_it, about_what = quote.about_what, quote = quote.quote)

And in quote.html I'm just showing them using e.g. {{=who_said_it}}.

Okay! So: import checks to see if the module is in sys.modules, and if it is, it returns it.

What that means is that when your webapp gets it's first request, it runs the quote function, imports the module, runs the code in the module, and returns a response. The next time your webapp gets a request it looks at import quote, sees that it has already been imported, and just uses the already imported quote object.

SO! What can you do? Make a function in your quote module that returns a random quote. Something like this.

def random_quote():
    # do all the spreadsheet opening and random number generation stuff. 
    quote = {}
    quote['who_said_it'] = worksheet.cell(random_number, 2).value
    quote['about_what'] = worksheet.cell(random_number, 3).value
    quote['quote'] = worksheet.cell(random_number, 4).value
    return quote

In your controller

import quotes

def quote():
    return quotes.random_quote()

NB: It's a bad idea to define a module called quote and then import it into a another module with a function called quote! Like really really bad. Don't reuse names like that. Weird things will happen. Everything should have it's own name. Giving things good, unique, names is part of the art of programming.

Thanks hansel, I'll give that a try later. Also, thanks for the tip about naming; I did start to think it was a bad idea when I had three different things with the same name...I need people like you that know what they're doing to keep me on the straight and narrow!

I remember in one of the first Computer Science lectures we had at Cambridge University, over a decade ago now, one of the lecturers was going through writing an example code snippet on the board. He came to a point where he needed a variable and turned to the students and solemnly declared "now comes the hardest problem you'll ever face as a software engineer - picking names for things". It made us all dutifully titter.

It wasn't until I'd been out in the industry for a few years that I realised he was far more right than I'd realised.

Cache invalidation and naming things...

Super, it works! Thanks for your help guys :-) I'll work on my naming...

No problem Abbie, drop us a line anytime if you have any more questions.