Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build an offline web app using Flask?

I'm prototyping an idea for a website that will use the HTML5 offline application cache for certain purposes. The website will be built with Python and Flask and that's where my main problem comes from: I'm working with those two for the first time, so I'm having a hard time getting the manifest file to work as expected.

The issue is that I'm getting 404's from the static files included in the manifest file. The manifest itself seems to be downloaded correctly, but the files that it points to are not. This is what is spit out in the console when loading the page:

Creating Application Cache with manifest http://127.0.0.1:5000/static/manifest.appcache offline-app:1

Application Cache Checking event offline-app:1

Application Cache Downloading event offline-app:1

Application Cache Progress event (0 of 2) http://127.0.0.1:5000/style.css offline-app:1

Application Cache Error event: Resource fetch failed (404) http://127.0.0.1:5000/style.css

The error is in the last line.

When the appcache fails even once, it stops the process completely and the offline cache doesn't work.

This is how my files are structured:

  • sandbox
    • offline-app
      • offline-app.py
      • static
        • manifest.appcache
        • script.js
        • style.css
      • templates
        • offline-app.html

This is the content of offline-app.py:

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/offline-app')
def offline_app():
    return render_template('offline-app.html')

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

This is what I have in offline-app.html:

<!DOCTYPE html>
<html manifest="{{ url_for('static', filename='manifest.appcache') }}">
<head>
    <title>Offline App Sandbox - main page</title>
</head>
<body>
<h1>Welcome to the main page for the Offline App Sandbox!</h1>
<p>Some placeholder text</p>
</body>
</html>

This is my manifest.appcache file:

CACHE MANIFEST
/style.css
/script.js

I've tried having the manifest file in all different ways I could think of:

CACHE MANIFEST
/static/style.css
/static/script.js

or

CACHE MANIFEST
/offline-app/static/style.css
/offline-app/static/script.js

None of these worked. The same error was returned every time.

I'm certain the issue here is how the server is serving up the files listed in the manifest. Those files are probably being looked up in the wrong place, I guess. I either should place them somewhere else or I need something different in the cache manifest, but I have no idea what. I couldn't find anything online about having HTML5 offline applications with Flask.

Is anyone able to help me out?

like image 662
Rafael Alencar Avatar asked Jun 27 '13 19:06

Rafael Alencar


People also ask

Can you build a website with Flask?

You can actually build powerful web applications with Python. And it's a lot of fun. In this tutorial, you will learn the Flask web framework, and you will build a website from scratch. Flask is a great Python framework for building web applications, and it is easy to learn.

Does Flask require a web server?

Although Flask has a built-in web server, as we all know, it's not suitable for production and needs to be put behind a real web server able to communicate with Flask through a WSGI protocol. A common choice for that is Gunicorn—a Python WSGI HTTP server.

Can you make desktop apps with Flask?

flask-desktop is a Python module that allows you to convert Flask apps into cross platform desktop apps with three lines of code.


1 Answers

I would have thought this one would work:

CACHE MANIFEST
/static/style.css
/static/script.js

But in any case, you should not hardcode the URLs for your static files. It's best to serve the manifest as a template (moved to the "templates" folder) so that you can use url_for to generate the path to the static files, something like this:

CACHE MANIFEST
{{ url_for('static', filename='style.css') }}
{{ url_for('static', filename='script.js') }}

Then in your HTML template you would have a reference to a route instead of a static file:

<html manifest="{{ url_for('manifest') }}">

And finally, you would add a new view function that returns the manifest:

from flask import make_response

@app.route('/manifest')
def manifest():
    res = make_response(render_template('manifest.appcache'), 200)
    res.headers["Content-Type"] = "text/cache-manifest"
    return res
like image 152
Miguel Avatar answered Oct 13 '22 01:10

Miguel