I have read some Q&A like load-static-content-with-cherrypy
However, I am unable to figure out how to do it to be shared by different paths.
I have the following Class:
class Root(Base):
#cherrypy.expose
def index(self):
return self.html_head()+self.header()+"Root"+self.footer()+self.html_end()
#cherrypy.expose
def help(self):
return self.html_head()+self.header()+"HELP"+self.footer()+self.html_end()
And the config file is:
[global]
server.socket_host = "127.0.0.1"
server.socket_port = 8080
server.thread_pool = 10
[/]
tools.staticfile.root = "/path/to/app/"
[/css/style201306.css]
tools.staticfile.on = True
tools.staticfile.filename = "css/style201306.css"
When accesing the css from /help I got a 404 error. Must I add a [path] entry for every method in my class where I want to serve the css file? Or must I use the [global] tag instead, though maybe I don't want to use it from other apps? What is the difference between an app config and a path config entry? Until know I was considering this as one App with 2 paths ("/" and "/help")
I am passing configuration like:
# Configuration
import os.path
tutconf = os.path.join(os.path.dirname(__file__), 'myconf.conf')
cherrypy.quickstart(root, config=tutconf)
Both webpages load the CSS the same way (actually, is the same code):
css/style201306.css
The problem is in your html itself use an absolute URL, there is no reason to use a relative url when is the same content, instead of:
<link rel="stylesheet" type="text/css" href="css/style201306.css" />
use
<link rel="stylesheet" type="text/css" href="/css/style201306.css" />
otherwise the browser will append the current URL, for example if the current URL is /help, then it will try to fetch:
/help/css/style201306.css
Related
This question already has answers here:
Link to Flask static files with url_for
(2 answers)
Closed 2 years ago.
I have a simple flask app that has a strange behaviour.
It seems that passing a route name is making the browser fetch the assets from another folder.
My html
<link href="./static/assets/main.css" rel="stylesheet">
Reserva já
My Flask route
#app.route('/work/<int:store_id>')
def stores(store_id):
mycursor.execute("SELECT * FROM stores WHERE store_id = %s" % store_id)
result = mycursor.fetchone()
return render_template("work.html")
The console says the browser now is looking for the css file here:
http://localhost:5000/work/static/assets/main.css
I dont understand why it puts the "work" in the path here. Im new to flask, maybe Im not understanding exactly how the routing works. I pass "work/22" because I want to pass two pieces of information, it this bad practice?
Thanks
This here is a relative path:
<link href="./static/assets/main.css" rel="stylesheet">
It is relative to the current location, which is /work/store_id. This works the same way as in a file system, so /work would be the current directory and the relative path therefore resolves to /work/static/assets/main.css.
If you want the path to be /static/assets/main.css, remove the leading dot:
<link href="/static/assets/main.css" rel="stylesheet">
I have this issue with Flask when i try running this code with Flask :
#app.route('/viz')
def root():
return render_template('page.html')
The file 'page.html' is in the templates folder, and contains some lines like this :
<link rel="stylesheet" href="static/main.css">
But when I execute my program, the file doen't look for main.css in the static directory, but in the viz/static direcory ( /viz is the route of the view).
How can I solve this issue ?
Thanks and sorry for my english.
You need a leading slash to tell the browser to use an absolute path.
<link rel="stylesheet" href="/static/main.css">
You need to place the static folder within the package or next to your module. See the Flask Quickstart documentation for more details. Without knowing more about your structure, my guess is your tree should look something like this:
- top level directory (e.g. your package "root")
| app.py
| static/
| viz/
Running on the devel server, I can render 0.0.0.0:8080/index.html without CSS fine, but no static files load. 0.0.0.0:8080/static results in "Not found" and 0.0.0.0:8080/static/style.css gets a 404.
All I've googled quotes or links to http://webpy.org/cookbook/staticfiles, which I feel like I've followed to point.
filetree
code.py
/web
...
/static
style.css
/images
...
/pages
index.html
code.py
import web
render = web.template.render('/home/keith/code/webpy/skeleton/pages/')
urls = (
'/', 'index',)
class index:
def GET(self):
return render.index()
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
/pages/index.html
...
<link rel="stylesheet" type="text/css" href="static/style.css" />
...
Would appreciate any help!
I tried running python code.py from a terminal window and the static files served fine! Before, I was using the terminal emulator in my IDE (Geany 1.24.1). So that was the problem, for whatever reason.
I've been working on testing Twitter Bootstrap with CherryPy 3.2.2, and have reviewed several of the SO posts, but have been unable to successfully get Cherry to run with my configuration files. I'm getting the infamous 404 error: "NotFound: (404, "The path '/' was not found.")".
This is my file setup:
/TwitApp (application directory)
testPy.py (my test application)
config.conf (configuration file to add CSS)
global.conf (global configuration for server socket, port, etc. I think this can go in config.conf?)
/css (CSS folder)
bootstrap.min.css
/js (javascript directory)
This is my testPy.py code:
#!/usr/bin/env python
import cherrypy
class HelloWorld:
def index(self):
return '''<!DOCTYPE html><html><head>
<title>Bootstrap Test</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap -->
<link href="../css/bootstrap.min.css" rel="stylesheet" media="screen">
</head><body>
<h1>Bootstrap Test</h1>
<button type="button" class="btn">Submit</button>
</body></html>'''
index.exposed = True
#I tried this example that I found in the documentation and on previous posts with the same 404 result:
#cherrypy.quickstart(HelloWorld(), "/", "config.conf")
#I tried this one when I reviewed another post on here:
cherrypy.config.update("global.conf")
cherrypy.tree.mount(HelloWorld(),"/","config.conf")
cherrypy.engine.start()
cherrypy.engine.block()
At one point the [global] section of my global.conf file was the top section of my config.conf file, but I split the two up when I started using the mount, start and block methods.
Here is my global.conf file:
[global]
server.socket_host = "127.0.0.1"
server.socket_port = 8080
log.screen: True
log.error_file: "/Users/myUser/tmp/newproject/cherrypy.error"
log.access_file: "/Users/myUser/tmp/newproject/cherrypy.access"
Here is my config.conf file:
[/]
tools.staticfile.root = "/Users/myUser/tmp/newproject/TwitApp"
[/css/bootstrap.min.css]
tools.staticfile.on = True
tools.staticfile.filename = "css/bootstrap.min.css"
This is the full error message:
404 Not Found
The path '/' was not found.
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/CherryPy-3.2.2-py2.7.egg/cherrypy/_cprequest.py", line 656, in respond
response.body = self.handler()
File "/Library/Python/2.7/site-packages/CherryPy-3.2.2-py2.7.egg/cherrypy/lib/encoding.py", line 188, in __call__
self.body = self.oldhandler(*args, **kwargs)
File "/Library/Python/2.7/site-packages/CherryPy-3.2.2-py2.7.egg/cherrypy/_cperror.py", line 386, in __call__
raise self
NotFound: (404, "The path '/' was not found.")
The articles I read through the most can be found here: Cherrypy returning NotFound: (404, "The path '/' was not found.") and here: Path Not Found in CherryPy. Can someone please advise what I'm doing incorrectly?
Take a look at https://github.com/btsuhako/bootstrap-cherrypy-jinja2
In the configuration files, it's easier to setup a static dir in your CherryPy app config file:
[/css]
tools.staticdir.on: True
tools.staticdir.dir: 'css'
[/js]
tools.staticdir.on: True
tools.staticdir.dir: 'js'
Final answer: I decided that I should just start troubleshooting, so I hacked down all of the CherryPy configurations and just did a basic cherrypy.quickstart(HelloWorld()) with the template I had. I was still getting the 404 error, so that meant that there was something fundamentally wrong with my code, not a config error. I kept looking through everything and then I found it. On vim, my code alignment was a little off and that's when I noticed that index.exposed = True was not set outside the index function! D'oh! I replaced it and now it's working with CSS, so anyone who's interested in learning how to implement CherryPy with CSS, there ya go!
I am using Flask as a web framework, and I am trying to implement the first example from the book Getting Started with D3, by Mike Dewar. I have a Python script named run.py and two directories, templates/ and static/, containing index.html and service_status.json, respectively. Unfortunately, my code is not rendering the data at all, nor is it producing any glaring errors.
This is what I have in run.py:
#!/usr/bin/env python
from flask import Flask, render_template, url_for
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
if __name__=="__main__":
port = 5000
app.debug = True
app.run( port=port )
This is what I have in templates/index.html:
<!DOCTYPE HTML>
<HTML>
<HEAD>
<META CHARSET="utf-8">
<SCRIPT SRC="http://d3js.org/d3.v3.min.js"></SCRIPT>
<SCRIPT>
function draw(data) {
"use strict";
d3.select("body")
.append("ul")
.selectAll("li")
.data(data)
.enter()
.append("li")
.text( function(d){
return d.name + ": " + d.status;
}
);
}
</SCRIPT>
<TITLE>MTA Data</TITLE>
</HEAD>
<BODY>
<H1>MTA Availability Data</H1>
<SCRIPT>
d3.json("{{ url_for( 'static', filename='service_status.json') }}",draw); // <---- BIG PROBLEM
</SCRIPT>
</BODY>
</HTML>
I am using Windows 7, Google Chrome, and Python 2.7.
If the JSON file is not going to change, then you should put it in the static directory and use
from flask import url_for
url_for('static', filename='service_status.json')
For this to work, also change the path in the JavaScript to '/static/service_status.json'
Static files like your json document, are by default served from a different directory from the templates - by default 'static'
You dont need to use the url_for call in your view, you can use it in your template:
d3.json("{{ url_for('static', filename='service_status.json') }}",draw);
So to summarise: 1) Move your json document in to the static folder (a folder called static along side your templates folder, by default), and 2) use the url_for call in your template to get the correct URI for your json document.
If you want to use a folder other than static, you can change that by passing static_folder to the Flask object contructor
You seem to be getting a 304 status code as you mentioned in earlier comments. I see that your JSON has the following date/time:
"Date": [
"12/15/2011"
],
"Time": [
" 7:35AM"
],
I am not 100% sure but this might help:
http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html#if-modified-since
Basically, it says that
"This request header is used with GET method to make it conditional: if the requested document has not changed since the time specified in this field the document will not be sent, but instead a Not Modified 304 reply.
Format of this field is the same as for Date:"
So, may be you can check the timestamp on the JSON and probably just do a fresh save ?