Access a layout template from a blueprint template folder - python

I have a blueprint with its own template folder. There is also a base layout template in the "top" templates folder. I want to access this template from a blueprint template. I tried the following but got a "Template Not Found" error.
{% extends "../../../../../templates/layout.j2" %}
The package looks like this:
__init__.py
├── modules
│ └── citrixlb
│ ├── citrixlb.py
│ └── templates
└── templates
└── layout.j2
I set up the blueprint's template_folder:
citrix = Blueprint('citrix', __name__, template_folder='templates', url_prefix='/citrix')
What is the correct way to reference a template from another template directory?

Flask's Jinja loader flattens the global folder and all blueprint folders into a common tree, prioritizing the global folder. So simply refer to the template as if it was at the top level location.
{% extends "layout.j2" %}
Note that by using the "j2" extension rather than ".html", you've probably inadvertently disabled automatic escaping. It is recommended that you use the ".html" extension for html templates.

Related

Python3 and pytest: jinja2.exceptions.TemplateNotFound:

i'm creating some unit tests and i'm facing this issue
FAILED test_views_home.py::test_index -
jinja2.exceptions.TemplateNotFound: index.html
this is part of my testing code:
templates = Jinja2Templates('templates')
def test_index():
#router.get('/', include_in_schema=False)
async def index(request: Request):
return templates.TemplateResponse('index.html', {'request': request})
client = TestClient(router)
response = client.get("/")
assert response.status_code == 200
assert '<!DOCTYPE html>' in response.text
and this is my folder structure:
root/
├── views/
│ ├── index.py
├── templates/
│ ├── index.html
├── tests/
│ ├── test_sorullo.py
i got:
FAILED test_views_home.py::test_index -
jinja2.exceptions.TemplateNotFound: index.html
I'm guessing i'm putting wrong
templates = Jinja2Templates('templates')
but i couldn't figure it out. I didn't find anything similar searching. What i'm doing wrong?
thanks!
The error says that Jinja2 template engine is unable to find the specified template file. Check your template directory and make sure the file index.html is present.
The template directory is set to "templates". So the Jinja2 engine will look for the templates files in the directory named "templates" in the same directory of your code file, If the template files are located in a different directory, you can specify the full path to the directory instead of just the directory name.
Try to add the full path of template directory. If it solves you can correct the directory path.

Unable to find flask template [duplicate]

I am trying to render the file home.html. The file exists in my project, but I keep getting jinja2.exceptions.TemplateNotFound: home.html when I try to render it. Why can't Flask find my template?
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def home():
return render_template('home.html')
/myproject
app.py
home.html
You must create your template files in the correct location; in the templates subdirectory next to the python module (== the module where you create your Flask app).
The error indicates that there is no home.html file in the templates/ directory. Make sure you created that directory in the same directory as your python module, and that you did in fact put a home.html file in that subdirectory. If your app is a package, the templates folder should be created inside the package.
myproject/
app.py
templates/
home.html
myproject/
mypackage/
__init__.py
templates/
home.html
Alternatively, if you named your templates folder something other than templates and don't want to rename it to the default, you can tell Flask to use that other directory.
app = Flask(__name__, template_folder='template') # still relative to module
You can ask Flask to explain how it tried to find a given template, by setting the EXPLAIN_TEMPLATE_LOADING option to True. For every template loaded, you'll get a report logged to the Flask app.logger, at level INFO.
This is what it looks like when a search is successful; in this example the foo/bar.html template extends the base.html template, so there are two searches:
[2019-06-15 16:03:39,197] INFO in debughelpers: Locating template "foo/bar.html":
1: trying loader of application "flaskpackagename"
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- /.../project/flaskpackagename/templates
-> found ('/.../project/flaskpackagename/templates/foo/bar.html')
[2019-06-15 16:03:39,203] INFO in debughelpers: Locating template "base.html":
1: trying loader of application "flaskpackagename"
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- /.../project/flaskpackagename/templates
-> found ('/.../project/flaskpackagename/templates/base.html')
Blueprints can register their own template directories too, but this is not a requirement if you are using blueprints to make it easier to split a larger project across logical units. The main Flask app template directory is always searched first even when using additional paths per blueprint.
I think Flask uses the directory template by default. So your code should be like this
suppose this is your hello.py
from flask import Flask,render_template
app=Flask(__name__,template_folder='template')
#app.route("/")
def home():
return render_template('home.html')
#app.route("/about/")
def about():
return render_template('about.html')
if __name__=="__main__":
app.run(debug=True)
And you work space structure like
project/
hello.py
template/
home.html
about.html
static/
js/
main.js
css/
main.css
also you have create two html files with name of home.html and about.html and put those files in templates folder.
If you must use a customized project directory structure (other than the accepted answer project structure),
we have the option to tell flask to look in the appropriate level of the directory hierarchy.
for example..
app = Flask(__name__, template_folder='../templates')
app = Flask(__name__, template_folder='../templates', static_folder='../static')
Starting with ../ moves one directory backwards and starts there.
Starting with ../../ moves two directories backwards and starts there (and so on...).
Within a sub-directory...
template_folder='templates/some_template'
I don't know why, but I had to use the following folder structure instead. I put "templates" one level up.
project/
app/
hello.py
static/
main.css
templates/
home.html
venv/
This probably indicates a misconfiguration elsewhere, but I couldn't figure out what that was and this worked.
If you run your code from an installed package, make sure template files are present in directory <python root>/lib/site-packages/your-package/templates.
Some details:
In my case I was trying to run examples of project flask_simple_ui and jinja would always say
jinja2.exceptions.TemplateNotFound: form.html
The trick was that sample program would import installed package flask_simple_ui. And ninja being used from inside that package is using as root directory for lookup the package path, in my case ...python/lib/site-packages/flask_simple_ui, instead of os.getcwd() as one would expect.
To my bad luck, setup.py has a bug and doesn't copy any html files, including the missing form.html. Once I fixed setup.py, the problem with TemplateNotFound vanished.
I hope it helps someone.
Check that:
the template file has the right name
the template file is in a subdirectory called templates
the name you pass to render_template is relative to the template directory (index.html would be directly in the templates directory, auth/login.html would be under the auth directory in the templates directory.)
you either do not have a subdirectory with the same name as your app, or the templates directory is inside that subdir.
If that doesn't work, turn on debugging (app.debug = True) which might help figure out what's wrong.
I had the same error turns out the only thing i did wrong was to name my 'templates' folder,'template' without 's'.
After changing that it worked fine,dont know why its a thing but it is.
You need to put all you .html files in the template folder next to your python module. And if there are any images that you are using in your html files then you need put all your files in the folder named static
In the following Structure
project/
hello.py
static/
image.jpg
style.css
templates/
homepage.html
virtual/
filename.json
When render_template() function is used it tries to search for template in the folder called templates and it throws error jinja2.exceptions.TemplateNotFound when :
the file does not exist or
the templates folder does not exist
Create a folder with name templates in the same directory where the python file is located and place the html file created in the templates folder.
Another alternative is to set the root_path which fixes the problem both for templates and static folders.
root_path = Path(sys.executable).parent if getattr(sys, 'frozen', False) else Path(__file__).parent
app = Flask(__name__.split('.')[0], root_path=root_path)
If you render templates directly via Jinja2, then you write:
ENV = jinja2.Environment(loader=jinja2.FileSystemLoader(str(root_path / 'templates')))
template = ENV.get_template(your_template_name)
After lots of work around, I got solution from this post only,
Link to the solution post
Add full path to template_folder parameter
app = Flask(__name__,
template_folder='/home/project/templates/'
)
My problem was that the file I was referencing from inside my home.html was a .j2 instead of a .html, and when I changed it back jinja could read it.
Stupid error but it might help someone.
Another explanation I've figured out for myself
When you create the Flask application, the folder where templates is looked for is the folder of the application according to name you've provided to Flask constructor:
app = Flask(__name__)
The __name__ here is the name of the module where application is running. So the appropriate folder will become the root one for folders search.
projects/
yourproject/
app/
templates/
So if you provide instead some random name the root folder for the search will be current folder.

jinja2 load template from string: TypeError: no loader for this environment specified

I'm using Jinja2 in Flask. I want to render a template from a string. I tried the following 2 methods:
rtemplate = jinja2.Environment().from_string(myString)
data = rtemplate.render(**data)
and
rtemplate = jinja2.Template(myString)
data = rtemplate.render(**data)
However both methods return:
TypeError: no loader for this environment specified
I checked the manual and this url: https://gist.github.com/wrunk/1317933
However nowhere is specified to select a loader when using a string.
You can provide loader in Environment from that list
from jinja2 import Environment, BaseLoader
rtemplate = Environment(loader=BaseLoader).from_string(myString)
data = rtemplate.render(**data)
Edit: The problem was with myString, it has {% include 'test.html' %} and Jinja2 has no idea where to get template from.
UPDATE
As #iver56 kindly noted, it's better to:
rtemplate = Environment(loader=BaseLoader()).from_string(myString)
When I came to this question, I wanted FileSystemLoader:
from jinja2 import Environment, FileSystemLoader
with open("templates/some_template.html") as f:
template_str = f.read()
template = Environment(loader=FileSystemLoader("templates/")).from_string(template_str)
html_str = template.render(default_start_page_lanes=default_start_page_lanes,
**data)
I tried using the FileSystemLoader, but that didn't immediately work for me. My code was all in a module (a subdirectory with an __init__.py file), so I was able to use PackageLoader instead. The Jinja documentation calls this "the simplest way" to configure templates:
my-proj
├── Pipfile
├── Pipfile.lock
└── app
   ├── __init__.py
   ├── app.py
   ├── constants.py
   └── templates
   ├── base.html.jinja
   └── macros.html.jinja
from jinja2 import Environment, PackageLoader
def generate_html(my_list):
env = Environment(loader=PackageLoader("app"))
template = env.get_template("base.html.jinja")
return template.render({ "stuff": my_list })

How to load templates from Flask extension

I'm developing a flask extension following this tutorial. The part of my extension are also templates. I want, by default, to use templates from flask extension unless user overrides them in a main flask application. The problem is that by default template path points to main_flask_app/templates. How to go over it? Thanks a lot.
The layout of your app, and separately your extension, should look like this:
myapp_project/
myapp/
__init__.py
models.py
...
static/
templates/
index.html
...
myext/
mypage.html # overrides default from ext
myext_project/
myext/
__init__.py
...
templates/
myext/
mypage.html # the default template from ext
...
Notice how the directory structure is the same. Adding a template with the same path to the app overrides the default on that path in the extension.
Your extension will make these templates available by registering a blueprint with the app. The blueprint should be set up to use the templates folder.
from flask import Blueprint
bp = Blueprint('myext', __name__, template_folder='templates')
class MyExt(object):
...
def init_app(self, app):
...
app.register_blueprint(bp)
...

Flask Blueprint can't find static folder

I've set up a Blueprint in my Flask application, but I can't seem to get my static folder to work. I keep getting 404 errors when it tries to reach them:
127.0.0.1 - - [11/Sep/2014 15:14:20] "GET /static/js/bootstrap.min.js HTTP/1.1" 404 -
127.0.0.1 - - [11/Sep/2014 15:14:20] "GET /static/static/css/bootstrap.min.css HTTP/1.1" 404 -
The css one also appends static twice. The JS has the correct /static but doesn't seem to work. Right now, my static folder is in the blueprint root path (app/dashboard). I tried putting it into app/static but I get the same exact errors.
I have the following set up:
app/dashboard/__init__.py:
from flask import Blueprint
dashboard = Blueprint('dashboard', __name__, template_folder='templates', static_folder='static')
from application.dashboard import controllers
app/__init__.py:
# Blueprints
from flask import Blueprint
from application.dashboard import dashboard
app.register_blueprint(dashboard)
In app/templates/layout.html, I have a line that references two static files as follows:
<link rel="stylesheet" type="text/css" href="{{ url_for('dashboard.static', filename='css/bootstrap.min.css') }}">
<script src="{{ url_for('dashboard.static', filename='js/bootstrap.min.js') }}"></script>
My app/dashboard/static directory:
$ tree application/dashboard/static/
application/dashboard/static/
├── css
│   ├── bootstrap-theme.css
│   ├── bootstrap-theme.css.map
│   ├── bootstrap-theme.min.css
│   ├── bootstrap.css
│   ├── bootstrap.css.map
│   └── bootstrap.min.css
├── fonts
│   ├── glyphicons-halflings-regular.eot
│   ├── glyphicons-halflings-regular.svg
│   ├── glyphicons-halflings-regular.ttf
│   └── glyphicons-halflings-regular.woff
└── js
├── bootstrap.js
└── bootstrap.min.js
Any idea what is going on here? How can I structure my Blueprint properly? I've followed the instructions on the Flask documentation and I get this error.
Thank you.
Look like you have issue with two same routes for application and blueprint. See my another answer part 3.
Your application route /static/<path:path> to .static endpoint.
Your blueprint route /static/<path:path> to dashboard.static endpoint, because you do not have url_prefix when register blueprint and have /static - static folder prefix.
So you can use one of next solutions:
use only application static folder.
set url_prefix when register blueprint.
use another static folder prefix for blueprint.
disable application static folder app = Flask(__name__, static_folder=None).
use hacks with static endpoint descriptor.
You need to add URL prefix for your blueprint, like so
app.register_blueprint(dashboard, url_prefix='/dashboard')
I had the same problem. Solution was to go to the __init__.py file for the Blueprint, then add static_folder="static" inside the statement defining the blueprint:
from flask import Blueprint
main = Blueprint('main', __name__ ,static_folder = "static")
from . import routes
Since the app is actually running as the Blueprint, main here, this tells it to look for the static folder inside the main package. It doesn't work if you add this to the __init__.py script for the app (ask me how I know this...)
Why not use nginx? It's faster in terms of performance and you don't have to write code to serve up static content.

Categories