File creation
We often want to perform an operation before a file is downloaded. This operation often involves creating the download file itself.
In this example, we create two temporary download files and report download progress to the client using a progress bar.
Relationship
We add a create_file_functions
relationship from DownloadBtn
to Function
.
@DownloadBtnManager.register
class DownloadBtn(DownloadBtnMixin, db.Model):
...
create_file_functions = db.relationship(
'Function',
order_by='Function.index',
collection_class=ordering_list('index'),
foreign_keys='Function.create_file_id'
)
...
class Function(FunctionMixin, db.Model):
...
create_file_id = db.Column(db.Integer, db.ForeignKey('download_btn.id'))
View function
We add the following view function to app.py
.
import string
from random import choices
@app.route('/file-creation')
def file_creation():
btn = DownloadBtn()
btn.cache = 'default'
btn.create_file_functions = [
Function(create_file0, msg='Hello, World!'),
Function(create_file1, msg=choices(string.ascii_letters, k=400))
]
db.session.commit()
return render_template('index.html', download_btn=btn)
Create file functions
Create file functions always take the download button to which they are related as their first argument. We can pass in additional arguments and keyword arguments by setting the Function's args
and kwargs
attributes.
In our 0th file creation function, we store Hello, World!
in a data URL. We cache the result by exiting the function early if the download button has already been clicked.
import time
from base64 import b64encode
def create_file0(btn, msg):
if btn.downloaded:
return
stage = 'Creating File 0'
yield btn.reset(stage=stage, pct_complete=0)
data = ''
for i, char in enumerate(msg):
data += char
yield btn.report(stage, 100.0*i/len(msg))
time.sleep(.5)
data = b64encode(data.encode())
url = 'data:text/plain;base64,' + data.decode()
btn.downloads = [(url, 'tmp_file0.txt')]
db.session.commit()
yield btn.report(stage, 100.0)
In our 1st file creation function, we store a random string of ascii letters in a data URL. Because we want to store a different random string each time the download button is clicked, we store the URL in the download button's tmp_downloads
attribute.
def create_file1(btn, msg):
stage = 'Creating File 1'
yield btn.reset(stage, 0)
data = ''
for i, char in enumerate(msg):
data += char
yield btn.report(stage, 100.0*i/len(msg))
time.sleep(.01)
data = b64encode(data.encode())
url = 'data:text/plain;base64,' + data.decode()
btn.tmp_downloads = [(url, 'tmp_file1.txt')]
yield btn.report(stage, 100)