Fastapi : jinja2.exceptions.TemplateNotFound: index.html - python

I am trying with the below code to redirect to login page using fastapi. I used TemplateResponse to redirect to index.html page which I already created inside the templates folder.
File structure as follows
- main.py
- templates -> index.html
- static
main.py
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")
#app.get("/", response_class=HTMLResponse)
async def login_page(request :Request):
return templates.TemplateResponse("index.html", {"request":request})
I tried doing it but I am getting an error "jinja2.exceptions.TemplateNotFound: index.html" and when I insert some HTML code statically it's working but TemplateResponse is not working properly. Even when I tried giving an entire path of the HTML file inside the templates folder it's giving a different error.
Please guide me on how to make this code work as I tried with different ways but in any case, this code is giving an error index.html template not found

I just had the same problem when I was doing unit testing and solved it as follows:
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
templates = Jinja2Templates(directory=str(Path(BASE_DIR, 'templates')))

I ran your code with the following and it worked:
uvicorn main:app --reload
I ran into that error this morning when running my own app with supervisord and gunicorn. I found that I had to dynamically set the template directory so that jinja2 knows where the files are:
templates = Jinja2Templates(directory=os.path.abspath(os.path.expanduser('templates)))
You could use Dependencies in FastAPI to redirect and force a user to login:
https://fastapi.tiangolo.com/tutorial/dependencies/

Related

Deploying flask app to cpanel, not routing properly, 500 errors everywhere

I followed along with a youtube tutorial learning how to create a Flask website, and it works perfectly on my local machine.
I created a subdomain in my cPanel and used the 'setup Python app' wizard to create the app, it worked. So I uploaded the Flask app I made to the server and installed all the requirements. went to the site and this is what I get:
Website
The home page is displayed (it shouldn't be, it should direct you to the login page) and it seems to be overlapping with the navbar. all the links in the navbar return a 500 error, with no log in the error reports on the cPanel.
I've been trying to get it to work for 3 days I can't get it to work.
File tree:
File Tree
The Website folder holds all the files and templates
run.py:
from Website import create_app
app = create_app()
if __name__ == '__main__':
app.run()
passenger_wsgi.py:
import imp
import os
import sys
sys.path.insert(0, os.path.dirname(__file__))
wsgi = imp.load_source('wsgi', 'run.py')
application = wsgi.app
Website.init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
from flask_mail import Mail
from Website.config import Config
db = SQLAlchemy()
bcrypt = Bcrypt()
login_manager = LoginManager()
login_manager.login_view = 'users.login'
login_manager.login_message_category = 'info'
mail = Mail()
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)
bcrypt.init_app(app)
login_manager.init_app(app)
mail.init_app(app)
from Website.users.routes import users
from Website.posts.routes import posts
from Website.main.routes import main
from Website.errors.handlers import errors
from Website.booking.routes import booking
app.register_blueprint(users)
app.register_blueprint(posts)
app.register_blueprint(main)
app.register_blueprint(errors)
app.register_blueprint(booking)
return app
Can anyone please help figure out what I've done wrong?
Problem seems to be with URL_for() command to route links
The home page is displayed (it shouldn't be, it should direct you to the login page) <
Could be because you need to add the login decorator to the route for the home page url. could also be because you're already logged in (you logged in to upload the files to your cpanel/hosting server and haven't yet logged out; you should try opening your app in a different browser or private window in same browser)
it seems to be overlapping with the navbar. <
This is usually due to path issues i.e. your app is not seeing the correct path for your static files (any stylesheets, images, etc). To confirm, copy the full url to your stylesheet and try to open it in a new browser tab. If you get a 404, that tells you your path is incorrect
Answering my own question.
The problem was with the url_for() command to route the pages together. Not sure what the problem was but it wasn't looking in the right place. I fixed it by going to the .htaccess file and adding
RewriteEngine On
RewriteRule ^http://%{HTTP_HOST}%{REQUEST_URI} [END,NE]
no more 500 errors and it could find the css file.

CSS not recognized when served with FastAPI

I have a FastAPI app built and an index, css and js file that work when opened directly, but I can't get the css file to show up when being served with FastAPI. I've tried troubleshooting in case the problem is a CORS issue, I've tried re-arranging the files so as to be in the same or different directories (and re-specifying the href path accordingly) but nothing has worked. This is my directory at this point:
working_directory
└── app
|__ index.html
├── style.css
└── main.js
With the app home route set up like so:
file_path = "index.html"
#app.get("/")
async def home():
return FileResponse(file_path)
Would I need to also provide the path to the css file within the file_path variable? The formats I've tried haven't worked thus far and errors with FastAPI aren't as well documented as with Flask or Django, for example.
My error looks like this:
GET http://localhost:8000/style.css net::ERR_ABORTED 404 (Not Found)
How would I get the web app to recognize my style.css file?
You need to actually serve the static files. Below's an example doing so with FastAPI. In a 'real world' scenario you would probably leave serving these files to a reverse proxy, like nginx.
Consider the following structure;
src
app/main.py
static/css/main.css
templates/index.html
main.py
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pathlib import Path
app = FastAPI()
app.mount(
"/static",
StaticFiles(directory=Path(__file__).parent.parent.absolute() / "static"),
name="static",
)
templates = Jinja2Templates(directory="templates")
#app.get("/")
async def root(request: Request):
return templates.TemplateResponse(
"index.html", {"request": request}
)
index.html
...
<link href="{{ url_for('static', path='/css/main.css') }}" rel="stylesheet">
...

BuildError when using redirect between py files in Flask

I have a main landing page that I would like to use for linking to separate modules in Flask. I can't seem to connect them using url_for or any other method. It will load main.html with the link to App 1, but it breaks right there.
I'm getting "werkzeug.routing.BuildError: Could not build url for endpoint 'app1'. Did you mean 'load_myapp' instead?"
It feels like I'm just missing maybe one thing, but I can't seem to figure out what.
Example of my file structure according to the Flask documentation:
my_app
setup.py
-my_app
__init__.py
app1.py
Setup.py:
from setuptools import setup
setup(
name='my_app',
packages=['my_app'],
include_package_data=True,
install_requires=[
'flask',
],
)
__init__.py:
from flask import Flask, render_template, url_for, redirect
app = Flask(__name__)
import my_app.app1
#app.route('/')
def index():
return render_template('main.html')
#app.route('/load_myapp')
def load_myapp():
return redirect(url_for('app1'))
app1.py
from flask import Flask, render_template
from my_app import app
#app.route('/app1')
def app1():
return render_template("app1.html")
Main.html:
<body>
App 1
</body>
Thanks ahead of time for any help.

How to add views to a blueprint in separate files

I have a huge application that was getting hard to update its views. To 'fix' this, I had separate the views into a few files, using blueprints. The problem is that the blueprints are also getting very big, because the long documentation that each view has and the different verifications that each view requires.
I had tried to do an import like this:
Where I have a main file that contains the Flask application (which imports the blueprint), a file that contains the blueprint and a file the imports the blueprint and configure the views in it. The problem is that with this approach the views are not rendered, because flow reasons.
The main file, in the root of a folder:
from flask import Flask
from source import test
application = Flask(__name__)
application.register_blueprint(test)
application.run()
The blueprint file, inside a subfolder in the root folder:
from flask import Blueprint
test = Blueprint('test', __name__)
The view file, inside the same subfolder as the blueprint file:
from .test import test
#test.route('/home', methods=['GET', 'POST'])
def home():
return 'home'
I had also tried to add the blueprint decorator to a declared function, this way the views are add to the blueprint in the blueprint file, but I don't think this is a good approach or a scalable approach - and it didn't work ^ - ^.
I expect to create a blueprint in a file, import the blueprint in other files and add views to the blueprint and then import the blueprint and add it to the Flask application.
You need to import the views content in blueprint file.
I have created the scenario and able to get the view. Additionally, I have updated the naming convention.
Folder structure:
.
├── app.py
└── blueprints
├── example_blueprint.py
├── example_views.py
└── __init__.py
app.py:
from flask import Flask
from blueprints.example_blueprint import bp
app = Flask(__name__)
app.register_blueprint(bp)
blueprints/example_blueprint.py:
from flask import Blueprint
bp = Blueprint('bp', __name__,
template_folder='templates')
from .example_views import *
blueprints/example_views.py:
from .example_blueprint import bp
#bp.route('/home', methods=['GET', 'POST'])
def home():
return 'home'
blueprints/__init__.py: Blank file
Output:
Running the application:
export FLASK_APP=app.py
export FLASK_ENV=development
flask run
requirements.txt:
Click==7.0
Flask==1.0.3
itsdangerous==1.1.0
Jinja2==2.10.1
MarkupSafe==1.1.1
pkg-resources==0.0.0
Werkzeug==0.15.4
Reference:
Flask documentation on Blueprints
In root folder change main file:
from flask import Flask
from source.listener import test
application = Flask(__name__)
application.register_blueprint(test)
application.run()
The blueprint file, inside a subfolder in the root folder:
listener.py
from flask import Blueprint
from source.view import home
test = Blueprint('test', __name__)
test.add_url_rule('/home', view_func=home,methods=['GET', 'POST'])
The view file, inside the same subfolder as the blueprint file:
from flask import request
def home():
if request.method == 'POST':
user = request.form['name']
return "Welcome "+user
else:
return 'home'
Get Request O/P:
Home
Post Request O/P:
Welcome username
The view module isn't discovered since only the Blueprint object is imported.
From the organization of your Blueprint and particularly the import that you have shared in your main file, I can deduct the existence of an __init__.py in the blueprint folder that exports the blueprint object.
Importing the views in that file should have the app discover the views registered in the blueprint.
i.e.
blueprint/__init__.py:
from .test import test
from . import views

Import Handlers - App Route with Flask

My File Directory:
app/
app.py
app/server/
views.py
I don't get any import errors with views, but I am not able to URL route to Views - I can only do it from app.py - how can I fix this issue? I've been stuck on this for 6 hours.
Code from app.py - how I import views
sys.path.append(os.path.join(os.path.abspath('.'), 'server'))
import views
And my url routing seems fine, so I am not sure where the problem lies:
#app.route("/login/", methods=['GET', 'POST'])
def login():
doSomething()
I feel the problem is more to do with url routing than importing files though.
Try from views import * instead of import views.
Also, instead of doing sys.path.append, add an empty file named __init__.py to the server directory, and you should be able to do something like from server.views import *.
Solution: Also make sure your view import is towards the bottom of your app file, below the app initialization and config and such.

Categories