I am trying to build a dependency graph from a render of a template and I am running into a bit of trouble trying to get good information out of jinja.
I want to be able to render a template and get back a list/set of all of the files that were used to render the template. For example:
# template.html
{% extend base.html %}
{% for partial in partials %}
{% include partial %}
{% endfor %}
And have it render and find out what files were used.
# deps.py
base_path = os.path.dirname(os.path.realpath(__file__))
jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(base_path))
template = jinja_env.get_template('template.html')
template.render({
"partials": [
"test1.html",
"test2.html",
],
})
# ???
looking_for = ['base.html', 'test1.html', 'test2.html']
I have checked out the AST tree and meta.find_referenced_templates(ast) but it only works when using a constant string for the include path.
Tried a custom extension looking at the tokens, but that has the same issues where I can see the variable name, but cannot get the values of the variable since it is done during the parsing/compiling phase.
Also tried overriding the {% include %} but wasn't sure how to do this correctly.
By using a custom loader I could get the values, but only if they have not been loaded before since the environment caches the loaded templates. (This solution may work if I disable the caching but then it has significant performance impact on rendering.)
How can I keep track of all the extend/include dependencies that are used for a single template render?
Related
I'm using webpack to build html templates using Django's templating language. Django templates contain variables and tags using {{ }} and {% %} syntax. Webpack has ignored these just fine and built the html templates as expected, except when parsing srcset tags.
Webpack errors when it tries to parse the following html:
<source srcset="{% static 'images/my-image.png' %}">
I'd like webpack to either ignore all srcset tags completely, or have some sort of # noqa equivalent which makes webpack simply not make changes to this row of the file.
Is that possible?
I don't believe this is the best solution, but one workaround which feels very hacky, is to create a global template variable that returns an empty string.
The template tag can be inserted between src and set so that webpack doesn't parse it as a srcset tag. Then when django renders the template, it replaces the template variable with an empty string (nothing).
# context processor
def dummy(request):
return {"pass": ""}
# add the context processor to your templates in settings.py
TEMPLATES[0]["OPTIONS"]["CONTEXT_PROCESSORS"].append(<path/to/dummy-context-processpr>)
src{{pass}}set="{% static 'images/my-image.webp' %} 480w, {% static 'images/my-image-800.webp' %} 800w"
Currently, I use the following code to include another HTML file:
{% include "machines/opennebula/resources.html" %}
I am adding another folder to add another version of resources.html (specifically to support OpenStack when I want to swap to using that cloud platform):
machines/openstack/resources.html
I want to have the path change based on whichever is set in a config file (which I incorporate into other parts of the file I'm working on using):
{{ cloudPlatform }}
I tried:
{% include "machines/{{ cloudPlatform }}/resources.html" %}
This worked when using it in association with the script tag however it hasn't worked with Django's include statement. My question is how do I make something equivalent (that works in HTML) with Django?
Unless I am doing things wrong, it seems like if you have nested templates (i.e., {% include %} a template within a template), you will sometimes need to call {% load static %} in multiple "layers" of the nest. For example, say I have templateA.html:
{% load static %}
<a href={% static "some/path" %}>Some Link</a>
{% include 'templateB.html' %}
And then in `templateB.html, I have:
{% load static %}
<a href={% static "some/other/path" %}>Some Other Link</a>
As far as I can tell from testing, I must include {% load static %} in both templates, because templateB.html does not know that I have already loaded the {% static %} tag.
My question is this:
Assuming that it is necessary to load the {% static %} tag twice (or more times depending on the amount of nesting), is there going to be a performance hit from this extra loading?
I am not sure what Django does under the hood when you load this tag, but my intuition is that you don't want to be loading and reloading static files. (Since we are talking about an open source project, I did actually try to look under the hood myself at how this templatetag is implemented, but it proved to be a little beyond my comprehension...).
Also, this question assumes that it is necessary to always load the tag this way. If there is something I am missing, I would be very interested to learn more. Thank you!
You have to write the tag in every template. In case of performance, you need not to worry as it never reloads or loads a separate new copy of static files.
There is no overhead. load static does not "load and reload static files"; it just makes available the (already-loaded) code in the staticfiles templatetags library for use in your template.
By using load you adding tags and filters from some app into the context for the current template. It just calls parser.add_library() for parser and updates the list of tags and filters for this particular template. You can check this method, and it gets called from load tag
If you don't want to load something you can add it in the builtins. For Django 1.9 you can configure it like this
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'builtins': ['django.templatetags.static'],
},
},
]
and for older versions
from django.template.loader import add_to_builtins
add_to_builtins('django.templatetags.static')
I would like to make a categories page.
{% for post in site.categories[CATEGORY_NAME] %}
<li>{{ post.title }} ({{post.date|date:"%-d %B %Y"}})</li>
{% endfor %}
Is it possible to use a page parameter to fill in CATEGORY_NAME? Then I could have one file category.html which could serve as the index page for multiple categories (i.e. category.html?name=food and category.html?name=animals.
I've found a few plugins that handle this, but it seems like overkill to require a plugin.
https://github.com/zroger/jekyll-categories
http://blog.nitrous.io/2013/08/30/using-jekyll-plugins-on-github-pages.html
Here's the most related forum post I could find.
https://groups.google.com/forum/#!topic/jekyll-rb/y-dq-63Uvy4
If I can't do this without a plug in, is there a good reason?
I think the correct answer is that Jekyll pages must be compiled to html before they are served. This is not possible if the liquid language takes a parameter.
I've been looking around everywhere and trying everything but i cannot seem te get my css file to work in a Django template.
My css i called style.css
the code in the template right now looks like:
{% load staticfiles %}
<link rel="stylesheet" href="{{ STATIC_URL }}style.css" type="text/css" media="screen" />
I'm still working on the development server.
In settings py I added:
STATICFILES_DIRS = (
"home/henk-jan/website/Template/Database")
django.contrib.staticfiles is installed in Installed_apps
can anyone help me with this?
Cheers, Henkes
Edit: My template (index.html) is in the same folder as my style.css the folder is: /home/henk-jan/website/Template/Database
From looking at your original post it would appear to me that your working at rendering your page from two separate angles.
First, you have {% load staticfiles %} which will load the templatetags associated with the staticfiles module. Second, inside your link element you are referencing {{ STATIC_URL }} which gets expanded via context.
From this I would recommend one of the following two courses of action.
1 - Utilize the staticfiles module and the templatetags you loaded in your template.
To do this you should modify your link element to read like this:
<link rel="stylesheet" href="{% static "style.css" %}" type="text/css" media="screen" />
Note that in this instance I have replaced the {{ STATIC_URL }} with the {% static %} templatetag. The {% static %} templatetag takes an argument which is the file you wish to prefix with the static URL, and expands into the complete string.
2 - Make use of context by modifying your view to render with context.
The {{ STATIC_URL }} variable is made available via request context. There are a number of useful variables that are, that you can rely on to get expanded if you want to utilize them. The trouble is that you have to ensure that you render your template with context which means you would potentially have to change one or more views.
As an example an overly simple view that renders without context would look like:
from django.shortcuts import render_to_response
def index_without_context(request):
return render_to_response("index.html")
While the same overly simple view rendered with context would look like this:
from django.shortcuts import render_to_response
from django.templates import RequestContext
def index_with_context(request):
return render_to_response("index.html",
context_instance=RequestContext(request))
As I stated above, by rendering your template with a RequestContext you get other variables and such that can be of use so it is a very viable option.
In the end it really depends on where you want to keep the logic that ensures your static files get your static URL rendered correctly at. If you want that logic inside the template itself I would recommend you go with the {% load staticfiles %} approach and use the {% static %} template tag. If you prefer to make use of the {{ STATIC_URL }} variable as well as having other potentially useful variables available then I would recommend modifying your view to be rendered with a RequestContext.
You can read more about the difference between using the context processor or a template tag in the Django docs section about this very topic:
https://docs.djangoproject.com/en/1.4/howto/static-files/#referring-to-static-files-in-templates
Is "home/henk-jan/website/Template/Database" a valid location? Maybe "/home/henk-jan/website/Template/Database" instead? Right now the preceding forward slash is missing.
If you are working on the development server, you will want to let Django serve the static content. When you go to production you will have your web server handle serving static content instead.
You will want STATIC_URL pointing to the path to your static content (in this case it looks like that would be /Template/Database/. It sounds like you have that working. Now you just need to tell Django to serve static content when in DEBUG mode. See this post: Django MEDIA_URL and MEDIA_ROOT