This question already has answers here:
Flask blueprint static directory does not work?
(6 answers)
Closed 4 years ago.
I'm working on creating a personal test-website for myself using Flask, however I discovered a behaviour I can not full get behind and could need some help with.
I have separated my website into indivudial chunks using Flask's blueprint system, because it makes sense for my case (since I want it to contain multiple smaller test-applications). I am suspecting that my problem is rooted in my project stucture, so I am giving a brief overview over what I did. Here is my (simplified) project setup:
>File structure:
root (contains some linux start scripts)
- run.py
- website (the actual flask project folder)
- __init__.py (registers blueprints)
- blueprints
- __init__.py (empty)
- website
- __init__.py (defines routes, creates blueprint)
- static (static files for this blueprint)
- css
- example.css
- templates (render templates for this blueprint)
- example.html.j2
- app1
- <Same structure as above>
- app2
- <Same structure as above>
- ...
>run.py
from website import createApp
createApp().run(debug=True)
>website/__init__.py:
from flask import Flask, render_template
def createApp():
app = Flask(__name__)
app.testing = True
# Website
from blueprints.website import website
app.register_blueprint(website())
# App1
from blueprints.app1 import app1
app.register_blueprint(app1())
# App2
from blueprints.app2 import app2
app.register_blueprint(app2())
...
return app
>website/blueprints/website/__init__.py:
from flask import Blueprint, render_template
bp = Blueprint("website", __name__, url_prefix="/",
template_folder="templates", static_folder="static")
def website():
return bp
#bp.route('/')
def index():
return render_template('example.html.j2')
>website/blueprints/website/templates/example.html.j2
<html>
<head>
<link rel="stylesheet", href="{{url_for('website.static', filename='css/example.css')}}">
<title>Test Page!</title>
</head>
<body>
This is a test page!
</body>
</html>
Expected result: The page should appear with the style defined in example.css
Actual result: Loading the example.css document results in a 404 error.
Since I've tried to deal with this for a few hours now I think I have nailed the problem down to Flask being weird when it comes to the root address.
Since the blueprint defines the address as url_prefix="/" I access it by typing "website.com" into my browser. (The browser tries to call the resource over "website.com/static/css/example.css", but get a 404 response.)
If I change the address to something like url_prefix="/test" and access the page via "website.com/test", the stylesheet will be loaded successfully. (The browser now tries to call the resource over "website.com/test/static/css/example.css", this time the document is found and loaded.)
Since this is supposed to be the main page I do want for it to use the root address though.
I would be grateful for someone to shine some light onto this and explain to me where my error lays.
Interesting question. The only thing I can think off is that you might have specified that website.com/static holds all your static files in your WSGI server script. Therefore, the flask app doesn't interfere which requests to website.com/static and these requests are handled by the WSGI server which can't find them in the folder.
Does this problem also occur when using the development server?
Can you try changing the static server in your WSGI setup to the website/blueprints/static/website folder?
And finally if this doesn't help, can you make a small github repo with this problem? Its pretty hard to reproduce this problem with these kinds of imports and filetrees.
Related
I'm super new to web development, but not new to programming as a whole. I'm extremely confused by this application which I was pulled into fixing because the person who normally does it can't anymore.
This may be a silly question, but I can't find the code or any HTML that contains the actual web pages. In the main folder, ~/myapp, there contains:
- README.txt
- build
- env
- bin
- include
- lib
- local
- man
- passenger_wsgi.py
- passenger_wsgi.pyc
- pip-selfcheck.json
- public
- favicon.gif
- favicon.ico
- quickstart.html
- sd.html
- tmp
- error.log
- favicon.gif
- favicon.ico
- get-pip.py
- phpinfo.php
- pylibs
- quickstart.html
- sd.log
- myapp_flask
Observations:
env/bin/, env/include/, and env/lib/ all have what appear to be versions of python in them.
env/local/ contains its own bin/, include/, and lib/ directories that contain the exact same thing as the others.
tmp contains the standard restart.txt used for Apache rails applications. (Note: touching this does restart the server, so this env/ directory is linked to the application itself.).
Questions:
Does anyone recognize this file structure? What application type is it? Php? Rails? Something else?
Does anyone know where I could look for the code that contains the actual web page? This is a full-fledged, live webpage that people have been using for a while, but I can't find the html (not even for the homepage). I've been searching for days, so I know I'm going about this wrong.
Additional notes:
This error occurs when I restart the web application with touch tmp/restart.txt/
Web application could not be started
An error occurred while starting the web application. It exited before signalling successful startup back to Phusion Passenger. Please read this article for more information about this problem.
Raw process output:
Traceback (most recent call last):
File "/usr/share/passenger/helper-scripts/wsgi-loader.py", line 26, in <module>
import sys, os, re, imp, threading, signal, traceback, socket, select, struct, logging, errno
File "/usr/lib/python2.7/logging/__init__.py", line 26, in <module>
import sys, os, time, cStringIO, traceback, warnings, weakref, collections
File "/usr/lib/python2.7/weakref.py", line 14, in <module>
from _weakref import (
ImportError: cannot import name _remove_dead_weakref
both quickstart.html contents are identical:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>DreamHost</title>
<link media="all" rel="stylesheet" type="text/css" href="http://dreamhost.com/wp-content/themes/dreamhost/style.css" />
</head>
<body id="domains">
<div class="w1">
<div class="w2">
<div id="wrapper">
<div id="header">
<strong class="comingsoon-logo">DreamHost Imagine the Web, Your Way</strong>
</div>
<div class="main" style="padding-bottom: 24px">
<h1>sendsomething.net Coming Soon!</h1>
<div class="holder">
<div class="content">
<p>The DreamHost customer who owns sendsomething.net has not yet uploaded their website or has chosen to leave this holding page active.</p>
<p>If you are the owner of this domain, you'll find your login information contained within the emails sent to you when your account was activated. Once logged in, you'll be able to delete this page (quickstart.html) and upload your new site.</p>
<p>Here are some helpful links for getting started:</p>
<p>
<img src="http://images.dreamhost.com/btn-orange-webpanel.png" alt="DreamHost Web Panel" title="DreamHost Web Panel" />
<img src="http://images.dreamhost.com/btn-blue-wiki.png" alt="DreamHost Wiki" title="DreamHost Wiki" />
<img src="http://images.dreamhost.com/btn-green-discussion.png" alt="DreamHost Discussion Forum" title="DreamHost Discussion Forum" />
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
Thank you for your time and assistance!
Edit:
Per request of answerer, Here are the contents of ~/myapp/myapp_flask/:
- .hg
- .hgignore
- backup_config.ini
- backup_db
- db_backups
- db_repo
- dbmanage.py
- doc
- dump.sql
- example_backup_config.ini
- instance
- migrate_dbs.py
- new.db
- new_bkp.db
- requirements.txt
- restored.db
- restored.dbe
- myapp
- __init__.py
- __init__.py.orig
- __init__.pyc
- app.py
- app.pyc
- forms.py
- forms.pyc
- helpers.py
- helpers.pyc
- static
- templates
- user.py
- user.pyc
- views.py
- views.pyc
- myapp.wsgi
- teste.db
- webfaction.db
Note: This might not be a complete answer, but it might be a starting place for one.
Possibly in answer to your first question, and based on the comments from earlier, this project looks to me like it might be a Flask web application. Flask is a Python microframework that can be used to build simple or complex web applications. I'm guessing this based on the following observations:
The passenger_wsgi.py file
The observation of the files ending in .py made by brombeer in the comments
The item at the bottom of your application structure list called myapp_flask
As far as the passenger_wsgi.py file, Passenger is a web application server used to run web applications written in things like Python, Ruby, or Node.js.
As far as brombeer's observation about the file extensions, files that end in .py are typically Python files.
As far as that myapp_flask item, if there are contents inside this file or folder, I wonder if it might contain the main web application code. Would it be possible to check that file or folder to see if it contains application code? Warning: It might contain sensitive data (e.g., passwords, secrets, or keys), so I don't know if it should be posted in your original post above.
So, I guess I touched on your second main question in that earlier response: you might be able to find the main web application code in the myapp_flask item. If nothing is there, however, you might be able to determine where the main application code is by looking at the contents of your passenger_wsgi.py.
In this example passenger_wsgi.py file in the Passenger documentation, it shows how an example (Django, in that case) application might be referred to in this type of file. If you open your passenger_wsgi.py in a text editor, it might a show a reference to the main application code on a line that contains the term application = (or something similar), like in the earlier example. Maybe this could help you know what the name of the application might be.
Then, you could possibly use grep to search for the application name in your file structure, if grep is available on your system. Maybe using a search command like: grep -r 'application-name' *. That might give you more clues as to where the main application code is located.
As far as the additional note about your ImportError: cannot import name _remove_dead_weakref error, I don't know if it's similar to this other question from the past. I would recommend caution, however, before changing up your Python 2 related setup based on answers in that other question thread, unless you are alright with whatever might happen along the way. I haven't tried out the answers myself from that thread.
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 am trying to create a very simple one-page Flask application for a python script that I have. The script requires multiple user inputs in a for-loop with the number of loops being user input as well.
Here is the code in my script to make it more clear:
def shared_books():
import requests as re
from bs4 import BeautifulSoup
import time
num_lists = int(input('Enter the number of lists you would like to search:'))
urls = []
page_counts = []
for i in range(num_lists):
urls.append(input(f'Enter the url for list {i + 1}:'))
page_counts.append(int(input(f'Enter the number of pages for list {i + 1}:')))
I want a simple HTML that will ask the user for the number of lists, then the URL and page count for each list as is shown in my function. Then it will run the entire function.
The HTML code I have right now is super simple and I don't want much else outside of the input parts:
<html>
<head>
<title>Goodreads-App</title>
</head>
<body>
<h1>Welcome to my app!</h1>
<<p>This app will allow you to see books that are
shared between multiple lists on goodreads</p>
</body>
</html>
Please let me know how I can set up this application!
Firstly, I suggest you take a look at the Flask docs. You are doing it right in terms of having a view function, but the input() python keyword doesn't work like that in Flask. Instead, you should render an html template which you can then put your form input field into. Here is an example:
from flask import Flask, render_template
#flask initialising stuff, read docs for info
#app.route("/home")
def home():
return render_template("home.html")
Flask runs on your computer's local server "localhost", which is not publicly accessible. It conventionally runs on port 5000, which gives the name "localhost:5000".
When someone visits "localhost:5000/home", flask will look for a file called "home.html" in a pre-designated templates folder – the default is a directory called "templates" which you should put your html files into.
So if this is your "home.html" file:
<html>
<head>
<title>Goodreads-App</title>
</head>
<body>
<h1>Welcome to my app!</h1>
<p>This app will allow you to see books that are
shared between multiple lists on goodreads</p>
</body>
</html>
When you load the page associated with a specific function, it will return a template which is rendered as html. The above should look something like this:
And that is how to start.
Thank you for the answers! I haven't quite solved the previous issue but have approached it from a different angle which is working now! I will potentially post again if I don't solve it.
I am using flask forms to do what I was trying.
This question already has answers here:
How to serve static files in Flask
(24 answers)
Link to Flask static files with url_for
(2 answers)
Closed 4 years ago.
I'm pretty new to python, even less experienced with flask, and I cannot figure out this issue. I have the following simple web page with jQuery functionality that works great when I double click the file and open it in a browser:
<!DOCTYPE html>
<html>
<head>
<script src="jquery-3.3.1.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
$("#updateBtn").on("click", function() {
text = "<h2>The div has been updated!</h2>";
$("#jQuery_div").html(text);
});
});
</script>
<div>
<h1>This is a non-jQuery div</h1>
</div>
<div id="jQuery_div">
<h2>This div should update with jQuery</h2>
</div>
<button id="updateBtn">update</button>
</body>
</html>
However, when flask delivers the web page on localhost:5000, the jQuery functionality is no longer present. My python is as follows:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def render():
return render_template("jquery_test.html")
if __name__ == "__main__":
app.run(port=5000, debug=True)
My app's file tree is:
/AJAX_practice
ajax_practice.py
/templates
jquery-3.3.1.js
jquery_test.html
I was trying to follow this tutorial when I couldn't get the "echo" button to work. In my efforts to debug, I have slowly chipped away and drastically simplified the program to the above code to see why I cannot get my jQuery to work through flask. I am still at a loss. I am running the flask app by pressing F5 in IDLE, with no errors in Python 2.7.13 Shell, and the Terminal (from which I started IDLE with $ sudo idle) showing:
my ip - - [date and time] "GET / HTTP/1.1" 200 -
my ip - - [date and time] "GET /jquery-3.3.1.js HTTP/1.1" 404 -
From this, my best guess is that flask cannot find the jquery.3.3.1.js file, though I have tried putting it everywhere in the file tree with no luck. I cannot use the script src to https for jQuery dependencies, as my server will eventually be on a non-internet connected LAN. Am I on the right track? If so, how does flask find and/or navigate jQuery dependencies? Can anyone point me towards some documentation that might help my fundamental understanding of this issue?
Any help on this matter would be greatly appreciated.
You are trying to serve JavaScript file from templates folder. Add a static folder and use that to serve static content.
in your case create a directory structure like "static/js/jquery.min.js"
and then add script reference like this
<script src="{{url_for('static', filename='js/jquery.min.js')}}"></script>
See this :
http://exploreflask.com/en/latest/static.html
If you don't want to keep it in "static" folder and use another local directory you can use send_from_directory as shown in this example :
https://stackoverflow.com/a/20648053/2118215
This has always worked for me with Flask in the past:
<script src="{{ url_for('static', filename='jquery-3.3.1.js') }}"></script>
'static' is the name of the folder it's in (and the 'static' folder is in the root of my project). You can edit this to suit your preferred structure and naming, so change 'static' to 'templates' if that's where you'd rather keep your jquery file, although I would recommend keeping it in a separate folder from your HTML templates, purely in the interests of keeping your project well organised.
I believe the path to jquery should be /templates/jquery-3.3.1.js
On me flask server when i serve jquery it has the full path from the home directory: /static/js/jquery.min.js
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/