I'm working on a Flask app that uses url_for to specify the route to some static assets (js, css, etc). Here's an example from one of the templates:
<script src='{{ url_for('static', filename='js/search.js') }}'></script>
When this gets rendered into html, the path looks like this:
<script src='/static/js/search.js'></script>
Is it possible to modify this behavior such that the leading slash is dropped from the rendered script path? The goal is to render the following:
<script src='static/js/search.js'></script>
I'd be very grateful for any insights others can offer on this question!
I was having a similar issue with loading a css file that was on a custom static path.
One fix could be to change the ROOT_DIRECTORY of the application, but this didn't work for my application as I only need to change the static path.
I used a combination of static_folder and static_url_path:
STATIC_URL_PATH = '/your/custom/path/static' # Where the css is stored
STATIC_FOLDER = 'your/custom/path/static'
app = Flask(__name__, static_folder=STATIC_FOLDER,
static_url_path=STATIC_URL_PATH)
As you can see, the main difference is the leading / in the beginning, but this made the app to be able to find the css.
Related
My project structure looks like this:
/project home
app.py
/templates/index.html
/templates/assets
and my index.html file has several references to relative stylesheets that look like this:
<link rel="stylesheet" href="assets/css/slick.css">
<link rel="stylesheet" href="assets/css/slick-theme.css">
Same for various JS files that exist in assets/js. Now when I load the page, I get this error:
Loading failed for the <script> with source “http://localhost:5000/assets/js/popper.min.js”. localhost:5000:564:1
There are many of these messages and in the python debugger I see:
127.0.0.1 - - [24/Dec/2019 18:29:16] "GET /assets/js/main.js HTTP/1.1" 404
I tried googling and changing this line in Flask
STATIC_URL_PATH = '/templates/assets/' # Where the css is stored
STATIC_FOLDER = '/templates/assets/'
app = flask.Flask(__name__, static_folder=STATIC_FOLDER,
static_url_path=STATIC_URL_PATH)
But still when I click the index.html page in templates its able to load fine with all the CSS and JS and images, but from Flask, its like the CSS is stripped out.
First, make sure that the templates folder is in the same directory as your app.py:
.
├── app.py
└── templates
└── assets
Then create the Flask instance like this:
STATIC_FOLDER = 'templates/assets'
app = Flask(__name__,
static_folder=STATIC_FOLDER)
1st, /templates and templates (without /) are 2 different paths. The 1st one refers to a templates folder under the root path / of your system, which certainly isn't the one you want. The 2nd one refers to a templates folder in the same directory, which is the one you want.
2nd, there is no need to specify static_url_path if it's just the same as the static_folder, because that's the default behavior ("Defaults to the name of the static_folder folder").
Then, in your HTML files, instead of hardcoding the paths to the assets folder, let Flask build the URL for you. See the Static Files section of the Flask docs:
To generate URLs for static files, use the special 'static' endpoint
name:
url_for('static', filename='style.css')
By default, it will look for static files under the static folder (ex. static/style.css) because that it is the default value for the static_folder parameter in the Flask constructor. When you set it to templates/assets, Flask will use that and will automatically build the correct URL with url_for.
<link rel="stylesheet" href="{{ url_for('static', filename='css/slick.css') }}">
Note:
Make sure that, when testing the loading of static files, clear your browser's cache first or test your app on private/incognito mode of your browser, to force re-downloading of static files.
I am trying to understand how to create a link to static files in jinja2.
Everything I look up relates to Flask whereas I am using just webapp2 at this stage.
My main.py file looks as follows:
import os
import urllib
from google.appengine.api import users
from google.appengine.ext import ndb
import jinja2
import webapp2
JINJA_ENVIRONMENT = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
extensions=['jinja2.ext.autoescape'],
autoescape=True)
class MainPage(webapp2.RequestHandler):
def get(self):
template = JINJA_ENVIRONMENT.get_template('/templates/base.html')
self.response.out.write(template.render())
class ConsultsPage(webapp2.RequestHandler):
def get(self):
template = JINJA_ENVIRONMENT.get_template('/templates/consults.html')
self.response.out.write(template.render())
class CreateConsultPage(webapp2.RequestHandler):
def get(self):
template = JINJA_ENVIRONMENT.get_template('/templates/create-consult.html')
self.response.out.write(template.render())
app = webapp2.WSGIApplication([
('/', MainPage),
('/consults', ConsultsPage),
('/schedule/create-consult', CreateConsultPage)
], debug=True)
My base.html template contains the links to the static files in "/css", "/js" "/images" etc.
When I look at the localhost:8080/ and localhost:8080/consults all the static files are working. Page looks fine.
However the next level in the structure localhost:8080/consults/create-consult is not linking to static files.
When I view source I see that the css link has rendered as localhost:8080/consults/css/style.css , when the actual location is localhost:8080/css/style.css.
I understand I may need to make all links dynamic via some environment variable called uri_for, but I can't find the correct way to implement this.
I tried to replace my css link with
href="{{ uri_for('static', filename='css/screen.css') }}"
I was told by App Engine uri_for not set.
Basically would like to know the correct process for setting uri_for and then how to incorporate it in the paths for my links to static files.
Any help appreciated.
uri_for() is a Flask-specific function; it matches the name static to a route, which in turn then can be used to generate a path (like /static/css/screen.css if the static route is configured to handle /static/<path:filename> urls).
You just need to hardcode the path as /css/screen.css, no need for functions.
Note the leading /; that makes it an absolute path, relative to your current host. For a page at http://localhost:8080/foo/bar, such a path is then prefixed with http://localhost:8080 to form http://localhost:8080/css/screen.css. When you deploy to the app engine, the hostname will be different.
You could store a prefix URL or path in a global, so you can easily swap out the path for a CDN later:
JINJA_ENVIRONMENT.globals['STATIC_PREFIX'] = '/'
and use that in your templates:
<style src="{{ STATIC_PREFIX }}css/screen.css"></style>
You can now alter all such URLs in one place, by setting the STATIC_PREFIX to a different value, including http://somecdn.cdnprovider.tld/prefix/.
I'm just starting out with Flask, and I was wondering what the best method for
dealing with how flask deals with static files when trying to use a premade CSS template.
Basically, I have downloaded a CSS template that I liked off the internet, but when if I simply drag the files into my flask application folder the CSS, JS, and image files do not work since they are not located in the static folder.
But if I move all the static files into the static folder, then I have to go through all the code and change the link urls, which is very time consuming.
The CSS Template I am using has an index.html that uses links like
<link rel = "stylesheet" href = "css/style.css" >
I have set both the static_folder = ""
and the static_url_path = "" in my flask app and I have moved the css, js, and image folders from the downloaded template into the base folder for the application, but the links are still not working.
Is there a better way to deal with using premade CSS templates with flask? Can I override the need to put css and js and image files in the static folder somehow? Thanks for your help!
(Sorry for opening this old post, but I'm on a badge hunt :])
There are several possible solutions, but the one I would recommend is to move the file style.css to folder <server_root>/static/css/.
Then create the flask app like app = Flask(__name__, static_url_path=''), what means that it still serves static files from the static/ folder, but on path / (so <server_root>/static/css/style.css is served on /css/style.css).
With this setup, your links href="/css/style.css" will work.
However, it's strongly recommended to use flask.url_for('endpoint', param='value') instead of /endpoint/url/value both in code and templates (surrounded with {{ ... }}) for all URLs - static files ('static', filename='css/style.css') and your own endpoints. So if your endpoint looks like this,
#app.route('/some/path/<variable>')
def some_endpoint(variable):
# do something and return response...
... you can use url_for('some_endpoint, variable='something') no matter what the actual URL (/some/path/something/ in this case) is. (Tested python 3.6.7; flask 1.0.2)
I'm trying to do the following:
Having a file structure like the following:
/app
/static
/start
/css
/js
- index.html
/templates
Id like to know how I can serve this index.html and make this load its CSS and JS without using url_for('static', filename='') or other kind of serving trough Flask.
Basically, I want to put http://local.com/start and trough Flask serve index.html which will load its own css and js like <link href="css/style.css" rel="stylesheet">
I tried send_from_directory('/static/start', "index.html") and app.send_static_file('index.html') but they don't work.
I also tried current_app.send_static_file('start/index.html') but this only serves the html. It doesn't make the index.html load its own CSS and JS.
I got the information from these links
How to serve static files in Flask
python flask - serving static files
Flask: How to serve static html?
They don't do what I want (or maybe I'm doing it wrong).
Thanks in advance, if there is more info needed just tell me.
You can load a regular html file as a jinja template. Just call render without any parameters.
I have a Pyramid app that I've been developing and viewing locally through http://localhost:6543, which is what the paster docs suggest. There are various assets, for example .css files, available in a static directory, which I have made available through config.add_static_view('static','static') When I view it through localhost everything works fine, my .css files are loaded, and all is well. However, when I view the app through my computer's hostname/IP address, the static assets aren't loaded.
A freshly-installed Pyramid paster scaffold displays the same behavior. I've gone through and followed the Pyramid narrative documentation through the step called viewing the application, and everything works as is described. But change the URL in the location bar from http://localhost:6543 to http://my.host.name:6543 and the style sheets don't get loaded.
The assets are available; type http://my.host.name:6543/static/pylons.css on a freshly-created Pyramid paster scaffold and you can read the contents of the css, but it's not loaded when the root page is loaded. Firebug indicates that those resources are requested, but never received.
What's going on here, and how can I make sure that my static assets are loaded when I request them through something other than localhost?
Edit to add some code. This is from the Pyramid starter paster scaffold, which I haven't modified and which exhibits the same behavior my application does; it can be considered a minimal example.
from package's __init__.py:
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
config = Configurator(settings=settings)
config.add_static_view('static', 'static', cache_max_age=3600)
config.add_route('home', '/')
config.scan()
return config.make_wsgi_app()
complete views.py:
from pyramid.view import view_config
#view_config(route_name='home', renderer='templates/mytemplate.pt')
def my_view(request):
return {'project':'TestProject'}
relevant line from templates/mytemplate.pt:
<link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen"
charset="utf-8" />
Where static/pylons.css is in the static directory under the root.
Again, opening http://0.0.0.0:6543 in the browser (FF10) works fine, http://my.host.name:6543 displays the page without style information; but http://my.host.name:6543/static/pylons.css gives me the style sheet text.
Without being able to look at your code it's a bit hard to answer this question. My guess based on a similar experience is that you might not be using the static_url method inside your templates. Below is another way to reference static assets in your templates:
<link rel="stylesheet" href="${request.static_url('app:static/css/app.css')}">
Are you using that? Using anything else will certainly cause the behaviour you are seeing.
There seems to be a problem if the application is installed to a path that is not the document route. You can see this discussed here.