I have tried reading the docs for Bottle, however, I am still unsure about how static file serving works. I have an index.tpl
file, and within it it has a css f
I've used Sanketh's template in the past but over time condensed it to an extension agnostic function. You just have to add extension-folder mappings in the ext_map dictionary. It defaults to static/ folder if an extension is not mapped explicitly.
import os.path
# Static Routes
@get('/<filename>')
def serve_static_file(filename):
ext = os.path.splitext(filename)[1][1:]
ext_map = {'image':['png','gif','jpg','ico'],'js':['js']}
sub_folder = next((k for k, v in ext_map.items() if ext in v),'')
return static_file(filename, root='static/'+sub_folder)
Rather than use regular expression matching for serving files as in Sanketh's answer, I'd prefer not to modify my templates and provide a path to the static files explicitly, as in:
<script src="{{ get_url('static', filename='js/bootstrap.min.js') }}"></script>
You can do this simply by replacing the <filename>
in the static route decorator with one of type :path
- like so:
@app.route('/static/<filename:path>', name='static')
def serve_static(filename):
return static_file(filename, root=config.STATIC_PATH)
The :path
matches an entire file path in a non-greedy way so you don't have to worry about changing templates when switching to production - just keep everything in the same relative folder structure.
As indicated in the documentation, you should serve static files using the static function and css is a static file. The static function handles security and some other function which you can find out from the source. The path argument to the static function should point to the directory wherever you store the css files
Just providing an answer here because a number of my students have used this code in an assignment and I have a bit of a concern about the solution.
The standard way to serve static files in Bottle is in the documentation:
from bottle import static_file
@route('/static/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root='/path/to/your/static/files')
in this way, all of the files below your static folder are served from a URL starting with /static. In your HTML, you need to reference the full URL path for the resource, eg:
<link rel='stylesheet' type='text/css' href='/static/css/style.css'>
The answer from Sanketh makes it so that any reference to an image, css file etc anywhere in the URL space is served from a given folder inside the static folder. So /foo/bar/baz/picture.jpg and /picture.jpg would both be served from static/images/picture.jpg. This means that you don't need to worry about getting the path right in your HTML code and you can always use relative filenames (ie. just src="picture.jpg").
The problem with this approach comes when you try to deploy your application. In a production environment you want the static resources to be served by a web server like nginx, not by your Bottle application. To enable this, they should all be served from a single part of the URL space, eg. /static. If your code is littered with relative filenames, it won't translate easily to this model.
So, I'd advise using the three line solution from the Bottle tutorial rather than the more complex solution listed on this page. It's simpler code (so less likely to be buggy) and it allows you to seamlessly move to a production environment without code changes.
To serve static files using bottle
you'll need to use the provided static_file
function and add a few additional routes. The following routes direct the static file requests and ensure that only files with the correct file extension are accessed.
from bottle import get, static_file
# Static Routes
@get("/static/css/<filepath:re:.*\.css>")
def css(filepath):
return static_file(filepath, root="static/css")
@get("/static/font/<filepath:re:.*\.(eot|otf|svg|ttf|woff|woff2?)>")
def font(filepath):
return static_file(filepath, root="static/font")
@get("/static/img/<filepath:re:.*\.(jpg|png|gif|ico|svg)>")
def img(filepath):
return static_file(filepath, root="static/img")
@get("/static/js/<filepath:re:.*\.js>")
def js(filepath):
return static_file(filepath, root="static/js")
Now in your html, you can reference a file like so:
<link type="text/css" href="/static/css/main.css" rel="stylesheet">
Directory layout:
`--static
| `--css
| `--fonts
| `--img
| `--js