How to serve static file in Flask - python

I have a google verification file that I need to have in my root directory. How do I serve it and set up the route correctly in my app.py file? I thought just having it in the static directory would do the trick.
In my app.py file:
import requests; requests = requests.session()
from flask import (
Flask,
g,
session,
request,
render_template,
abort,
json,
jsonify,
make_response
)
from jinja2 import TemplateNotFound
app = Flask(__name__)
...
#app.route('/ping')
def ping():
return "OK"
"""
Catch-All Route
first looks for templates in /templates/pages
then looks in /templates
finally renders 404.html with 404 status
"""
#app.route('/', defaults={'path': 'index'})
#app.route('/<path:path>')
def show_page(path):
if session.get('tracking_url'):
session['session_url'] = False
templates = [t.format(path=path) for t in 'pages/{path}.html', '{path}.html']
g.path = path
try:
return render_template(templates, **site_variables(path))
except TemplateNotFound:
return render_template('404.html', **site_variables(path)), 404
application = app
if __name__ == '__main__':
app.run('0.0.0.0', debug=True)
I've tried adding this but it didn't work:
#app.route('/myfile.html')
def myfile():
return send_from_directory('/static', 'myfile.html')

For a one-off file that Google looks for in the root, I'd just add a specific route:
from flask import send_from_directory
#app.route('/foobar_baz')
def google_check():
return send_from_directory(app.static_folder, 'foobar_baz')
You are free to add in test in show_page(path) to try and serve path with send_from_directory() before you test for a template, of course; the second filename argument can take relative paths.

Related

Reference app location in a Flask Blueprint

I have a blueprint where I have an upload form. I am attempting to save the files, but I cannot figure out how to reference the correct directory. When I use app.instance_path, it gives the error message:
NameError: name 'app' is not defined
How can I declare the correct folder location to store the file from within a Flask Blueprint?
Here is my init.py file:
# External libraries
from flask import Flask
# Import the resources
from . import students
def create_app(configfile=None):
app = Flask(__name__)
app.register_blueprint(students.bp)
return app
Here is my students.py blueprint file:
import os
from flask import (
Blueprint, flash, g, redirect, render_template, request, session, url_for
)
from werkzeug.utils import secure_filename
from SIMPLE.forms import ImportStudentsForm
bp = Blueprint('students', __name__, url_prefix='/students')
#bp.route('/import', methods=('GET', 'POST'))
def import_students():
# Load the register form
form = ImportStudentsForm(request.form)
if form.validate_on_submit():
f = request.files['file']
filename = secure_filename(f.filename)
f.save(os.path.join(
app.instance_path, 'uploads', filename
))
# Flash success
flash('Sucessfully registered.', 'success')
return render_template('students/batch_import_students.html', form=form)
Any guidance would be much appreciated. Thanks.
You get the error because you have not imported app in students.py. You could import it (and run the risk of circular imports) but a more elegant way is to get the app instance through flask.current_app.
Add from flask import current_app to the top of students.py and replace app.instance_path with current_app.instance_path.
Try this ::
from flask import current_app
AND
f.save(os.path.join(current_app.instance_path, 'uploads', filename))
You are using application factory. So there is no 'app' object here. Whatever app flask is currently using can be fetched with current_app and then you can work with it.
Also, if the instance_path doesn't work, try current_app.root_path

Flask blueprint for upload of files not getting route

Hey I am building a simple prototype in Flask and I am somehow missing something. The route to the upload is missing otherwise it's the pretty standard tutorial and I have pretty much everything working besides it's not adding the route. I have no clue why the route isn't there the debug simply gives a 404.
My routes in init.py looks like this
#app.route('/hello')
def hello():
return 'Hello, World!'
#app.route('/')
def index():
return render_template('home.html')
from . import uploader
app.register_blueprint(uploader.bp)
from . import db
db.init_app(app)
from . import auth
app.register_blueprint(auth.bp)
return app
And my uploader.py looks like this
from flask import (
Blueprint, flash, g, redirect, render_template, request, session, url_for
)
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileRequired
from werkzeug.utils import secure_filename
from flaskr.db import get_db
bp = Blueprint('uploader', __name__, url_prefix='/upload')
#bp.route('/upload', methods=('GET', 'POST'))
def upload():
if form.validate_on_submit():
f = form.photo.data
filename = secure_filename(f.filename)
f.save(os.path.join(
app.instance_path, 'photos', filename
))
return redirect(url_for('index'))
return render_template('upload.html', form=form)
I am probably not declaring something the right way but I don't know what.
The issue wasn't in my code but on my system. I fixed this by recloning the repo I already had which was working. I have no clue what broke it.

Flask returning random template for 404 errors

Flask keeps returning a weird 404 default template and ignores my custom made template. I have no idea why.
Here is my init
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
db.init_app(app)
#Fixes flask db upgrade to allow deleting columns
with app.app_context():
if db.engine.url.drivername == 'sqlite':
migrate.init_app(app, db, render_as_batch=True)
else:
migrate.init_app(app, db)
login.init_app(app)
babel.init_app(app)
bootstrap.init_app(app)
moment.init_app(app)
app.logger.setLevel(logging.INFO)
app.logger.info('Bob startup')
app.redis = Redis.from_url(app.config['REDIS_URL'])
app.task_queue = rq.Queue('offutt-tasks', connection=app.redis)
from app.errors import bp as errors_bp
app.register_blueprint(errors_bp)
from app.main import bp as main_bp
app.register_blueprint(main_bp)
return app
from app import models
Here is my init in my errors folder:
from flask import Blueprint
bp = Blueprint('errors', __name__)
from app.errors import handlers
Finally here is my handlers page with the routes.
from flask import render_template, request
from app import db
from app.errors import bp
#from app.api.errors import error_response as api_error_response
def wants_json_response():
return request.accept_mimetypes['application/json'] >= \
request.accept_mimetypes['text/html']
#bp.errorhandler(404)
def not_found_error(error):
#if wants_json_response():
# return api_error_response(404)
return render_template('errors/404.html'), 404
#bp.errorhandler(500)
def internal_error(error):
db.session.rollback()
#if wants_json_response():
# return api_error_response(500)
return render_template('errors/500.html'), 500
my 404.html renders fine when i write a route to go directly to it, but the errorhandler does not seem to be working at all. All it renders is a page saying "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."
Any ideas?
You need to use app_errorhandler() to use it for all requests, even outside of the blueprint doc. E.g.
#bp.app_errorhandler(404)
def not_found_error(error):
....

Flask Configuration for Sharing Resources Across Blueprints

I have an extremely large application that is factored into many blueprints. I need to configure the entire application to save files into a directory when a user uploads files. So I am setting ["SESSION_FILE_DIR"] = 'C:/some/path' to the path where files would live after upload in the app.py file.
The documentation reads that configuration settings are shared across the blueprints. I'm experiencing one issue that is not working and below is a stripped down example to replicate my problem to support my question. So, to debug I've created an extremely simple version just printing the path to screen to see what is happening.
If I head over to the URL .../print_dir then the ["SESSION_FILE_DIR"] = 'C:/some/path' is printed to screen. However, if I head over to the URL defined within the blueprint .../new then I am given an error of NameError: name 'server' is not defined.
How can I configure my app such that the same ["SESSION_FILE_DIR"] can be used across blueprints?
The contents of my main app.py are as follows:
from flask import Flask, render_template, request, session
from flask_session import Session
import tempfile
server = Flask(__name__)
server.config["SESSION_PERMANENT"] = False
server.config["SESSION_TYPE"] = "filesystem"
server.config["SESSION_FILE_DIR"] = 'C:/some/path'
server.secret_key = 'abcdefg'
### Import and Register Blueprints
from tools.routes import my_bp
server.register_blueprint(my_bp)
#server.route('/')
def homepage():
return "Hello"
#server.route('/print_dir')
def homepage2():
return server.config["SESSION_FILE_DIR"]
if __name__ == '__main__':
server.run(debug=True)
and now suppose the blueprint lives in a subdirectory called tools and contains the following:
from flask import Flask, render_template, request, session, Blueprint
from flask_session import Session
my_bp = Blueprint("my_bp", __name__)
#my_bp.route('/new', methods=['POST', 'GET'])
def path():
path = server.config["SESSION_FILE_DIR"]
return path
To access the app.config from within a Blueprint, you can import current_app from flask.
Example:
# ./app.py
from flask import Flask
from views.blueprint import bp
app = Flask(__name__)
# Set the config you want:
app.config['IMPORTANT_DIRECTORY'] = '~/path/to/important/directory'
# Register your blueprint
app.register_blueprint(bp)
# ./views/blueprint.py
from flask import Blueprint, current_app
bp = Blueprint('bp', __name__)
#bp.route('/path')
def get_path():
# access the config
path = current_app.config['IMPORTANT_DIRECTORY']
return path
You can find more info in the api docs for flask.

Where do I put my templates folder in a Flask app?

I'm trying to use render_template in my Flask app:
# -*- coding: utf-8 -*-
from flask import Flask, render_template, redirect, url_for, request
app = Flask(__name__)
#app.route("/")
def hello_world():
return "Hello World", 200
#app.route('/welcome')
def welcome():
return render_template("welcome.html")
#app.route("/login", methods=["GET", "POST"])
def login():
error = None
if request.method == "POST":
if request.form["username"] != "admin" or request.form["password"] != "admin":
error = "Invalid credentials. Please try again!"
else:
return redirect(url_for("home"))
return render_template("login.html", error=error)
app.run(debug=True)
I think that my app can't see welcome.html (and the templates folder) because I always get a "Internal Server Error" and no HTML page.
In a single folder, I have app.py the static folder and the templates folder (with the HTML file).
What's wrong here?
Does your python script have all the necessary bits of a minimal Flask application?
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/welcome')
def welcome():
return render_template("/welcome.html")
if name== "__main__":
app.run()
You probably don't need a / in the name of the template.
(i.e. 'welcome.html', not '/welcome.html').
See the documentation for render_template.
It works with or without the slash.
Can you share the folder structure, and the script that you are executing (such as a init.py)
try looking at this (it's my repo for my webpage), to see if you might have missed something..

Categories