What I’m trying to do:
I have a dashboard form and I’d like to be able to download it in PDF. The problem is, there’s a background task running in this dashboard form, and when I click on the download button, the task is not done running yet and I could not download the full information displayed on the form (which are all there once the background task is done running)
What I’ve tried and what’s not working:
I tried using time.sleep() with varying values of sleep time, it did not work.
This is my app https://anvil.works/build#clone:FKESPE75DVY2EGG6=XZ25GAQU7N4MAT3WSE3O5FOI
When you type in a value at the text field, after waiting for 10m the value will be displayed. However, if you download the file, the value will not be displayed. This is a very simplified version of my actual app and I used time.sleep(10)
because that’s normally how long it takes for the server code in my app to return a desired value.
thanks for the excellent clone link.
The problem is that the pdf waits for the form to render which happens once the form show event has finished executing. So using the timer doesn’t work here since the form has finished rendering already.
For this example you probably want to create a timer like function that blocks and prevents the __init__
method from completing. (this way we delay the rendering of the pdf form)
Something like this
def __init__(self, **properties):
...
while not self.task.is_completed():
from time import sleep
sleep(.5)
self.label_2.text = self.task.get_return_value()
Thank you for your answer! Unfortunately I have anvil.server.TimeoutError: Server code took too long
with just sleep(.3)
in my real application. The form render normally but when I try to download it it had this error.
timeout errors occur if a server function takes more than 30 seconds.
So I would suggest adjusting the logic of your function and return the rendered pdf from the background task.
Currently, however, you can’t return media objects from background tasks
.
A workaround would be to store the pdf in a datatable.
Then return the id of the row from the background task.
When the background task is complete you can get the media from the datatable by the row id
def timer_1_tick(self, **event_args):
"""This method is called Every [interval] seconds. Does not trigger if [interval] is 0."""
with anvil.server.no_loading_indicator:
if self.task.is_completed():
self.timer_1.interval = 0
pdf_row_id = self.task.get_return_value()
pdf = anvil.server.call('get_pdf', pdf_row_id)
download(pdf)
Here’s the adjusted clone to better explain what I mean.
https://anvil.works/build#clone:X6WVOLV6RV4PTENI=UGHVQRS3RSJDF4IORDNGMCWP
4 Likes