9

I've set up a Blueprint in my Flask application, but I can't seem to get my static folder to work. I keep getting 404 errors when it tries to reach them:

127.0.0.1 - - [11/Sep/2014 15:14:20] "GET /static/js/bootstrap.min.js HTTP/1.1" 404 -
127.0.0.1 - - [11/Sep/2014 15:14:20] "GET /static/static/css/bootstrap.min.css HTTP/1.1" 404 -

The css one also appends static twice. The JS has the correct /static but doesn't seem to work. Right now, my static folder is in the blueprint root path (app/dashboard). I tried putting it into app/static but I get the same exact errors.

I have the following set up:

app/dashboard/__init__.py:

from flask import Blueprint
dashboard = Blueprint('dashboard', __name__, template_folder='templates', static_folder='static')
from application.dashboard import controllers

app/__init__.py:

# Blueprints      
from flask import Blueprint
from application.dashboard import dashboard
app.register_blueprint(dashboard)

In app/templates/layout.html, I have a line that references two static files as follows:

<link rel="stylesheet" type="text/css" href="{{ url_for('dashboard.static', filename='css/bootstrap.min.css') }}">
<script src="{{ url_for('dashboard.static', filename='js/bootstrap.min.js') }}"></script>

My app/dashboard/static directory:

$ tree application/dashboard/static/
application/dashboard/static/
├── css
│   ├── bootstrap-theme.css
│   ├── bootstrap-theme.css.map
│   ├── bootstrap-theme.min.css
│   ├── bootstrap.css
│   ├── bootstrap.css.map
│   └── bootstrap.min.css
├── fonts
│   ├── glyphicons-halflings-regular.eot
│   ├── glyphicons-halflings-regular.svg
│   ├── glyphicons-halflings-regular.ttf
│   └── glyphicons-halflings-regular.woff
└── js
    ├── bootstrap.js
    └── bootstrap.min.js

Any idea what is going on here? How can I structure my Blueprint properly? I've followed the instructions on the Flask documentation and I get this error.

Thank you.

darksky
  • 20,411
  • 61
  • 165
  • 254

4 Answers4

12

Look like you have issue with two same routes for application and blueprint. See my another answer part 3.

Your application route /static/<path:path> to .static endpoint.

Your blueprint route /static/<path:path> to dashboard.static endpoint, because you do not have url_prefix when register blueprint and have /static - static folder prefix.

So you can use one of next solutions:

  1. use only application static folder.
  2. set url_prefix when register blueprint.
  3. use another static folder prefix for blueprint.
  4. disable application static folder app = Flask(__name__, static_folder=None).
  5. use hacks with static endpoint descriptor.
Community
  • 1
  • 1
tbicr
  • 24,790
  • 12
  • 81
  • 106
  • Hmm, I'm not sure I understand what the solution is. Is it possible not set a url prefix, but have the static folder go to `dashboard/static`? – darksky Sep 12 '14 at 14:44
  • It seems like whatever I add, it doesn't take effect on the Blueprint. It only takes effect if I add it to app. Why is that? – darksky Sep 12 '14 at 14:50
  • 1
    If you want avoid application static folder route usage, you should disable it: `app = Flask(__name__, static_folder=None)`. Please see details of `url_prefix` or use `url_for('dashboard.static', filename='css/bootstrap.min.css')` to get real link. Problem because you have two endpoins with same route - one always not work. – tbicr Sep 12 '14 at 16:10
  • 1
    The trick was to just set the static_folder on app to None. Even though I point directly to the route, it does not work. Any idea why? I already did use the proper url_for. – darksky Sep 12 '14 at 16:43
  • As I said you has two endpoins one for app `.static` and one for blueprint `dashboard.static`. This two endpoints have same route `/static/`. So when you make `url_for('.static', filename='test.css')` or `url_for('dashboard.static', filename='test.css')` it will return `/static/test.css`. When you do request then flask route system get path `/static/test.css` and iterate for each route with priority, when it found first (app endpoint in your case) endpoint which satisfy route this endpoint will be returned and called dispatcher. – tbicr Sep 12 '14 at 17:38
1

You need to add URL prefix for your blueprint, like so

app.register_blueprint(dashboard, url_prefix='/dashboard')
Thanh DK
  • 4,257
  • 3
  • 23
  • 18
1

I had the same problem. Solution was to go to the __init__.py file for the Blueprint, then add static_folder="static" inside the statement defining the blueprint:

from flask import Blueprint

main = Blueprint('main', __name__ ,static_folder = "static")

from . import routes

Since the app is actually running as the Blueprint, main here, this tells it to look for the static folder inside the main package. It doesn't work if you add this to the __init__.py script for the app (ask me how I know this...)

karuhanga
  • 3,010
  • 1
  • 27
  • 30
pelon
  • 129
  • 1
  • 2
-1

Why not use nginx? It's faster in terms of performance and you don't have to write code to serve up static content.

michael salmon
  • 398
  • 4
  • 12
  • 2
    I'll be using a web server for production. I am testing locally for now. – darksky Sep 13 '14 at 15:07
  • Sure, but nginx is easy to run locally and less complicated than coding into flask a set of blueprints. Also it will help ensure what you develop against is tested before you launch it into your prod environment. – michael salmon Sep 15 '14 at 18:53
  • 5
    Good advice, but it's like answering "I'm having trouble implementing a linear sort method for a list class. Am I making a syntax error somewhere?" with "Why not use a RB-tree? It's not too hard, and it's consistently `O(logn)`." – eenblam Dec 21 '15 at 15:38