I'm trying to learn Django at the moment and am trying to make sure I'm not doing anything stupid.
I'm in the process of making my web page more modular in the sense that I am removing hardcoded values in the template (base .html). Doing so, I'm trying to convert hardcoded CDN references (jquery, bootstrap, etc.) to modular pieces that can be included in every web page. Doing so will allow me to change a single file in the future, instead of being forced to go to every web page and make that change.
However, I'm slightly confused. I'm trying to determine if it would make sense to copy them into a html file and use Django's {% include '' %} template tag to directly include the cdn portions, or if using Django's static include would be more appropriate.
So what exactly is the best route? It seems like it would be very easy to use template includes for everything static in all honesty. Why not use it to include javascript or css?
Websites generally need to serve additional files such as images, JavaScript, or CSS. In Django, we refer to these files as “static files”.
We call them 'static' simply because they aren't dynamic i.e the contents of these files are relatively fixed, either by design or by it's intrinsic characteristics (eg: binary content like images) and thus does not need to processed by our application server.
We differentiate them from other files because it's advisable to serve these static files at a lower level, for example, using nginx. This allows us to serve these files faster as is which leads to performance gains. It also allows easy caching.
But when using a CDN, you offload this work from your server to somebody else's server.
Now coming back to your question. You shouldn't have to declare your resources in every template. Usually, base.html contains the base of the page which can then me extended (read: template inheritance) by more specific (children) templates.
To understand this quickly, here's an example:
base.html:
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="~~CDN HERE~~">
<script src="~~CDN HERE~~"></script>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
article.html
{% extends "app/base.html" %}
{% load static %}
{% block body %}
<h1>{{ page_title }}</h1>
<img src="{% static 'app/img/detective.png' %}" alt="detective" />
{{ page_content | safe }}
{% endblock %}
Now for every article on your site, you render the article template which automatically extends the base removing the need to mention your css/js files for multiple pages.
If you're using different resource files for different pages, you can creation an additional block like {% block css %}{% endblock %}
and then add this to your article.html
{% block css %}
<link rel="stylesheet" href="{% static 'app/css/article.css' %}">
{% endblock %}
Notice how I'm using static for image, which is served directly by nginx.
Theoretically, you can club your CDN links into a file and then include it in base.html, but it just leads over modularity which causes redundant complexity.
Let me know if you have any issues!
Related
I'm new to UI web development with Flask and have tried some sample projects with Flask-Bootstrap. Is it possible to use a custom Bootstrap "theme" with Flask-Bootstrap? I'd like to use this theme for my website: https://github.com/kristopolous/BOOTSTRA.386
But because I'm relatively new to UI stuff/JS/CSS, I can't tell if it's possible to use the Bootstrap.386 theme with Flask-Bootstrap.
Can anyone with experience tell me this if this is technically feasible and maybe point me towards a tutorial or something where someone has done similar? I haven't had much luck with Googling.
Flask-Bootstrap has a built-in base template with some pre-defined macros, you can rewrite the styles macro to use your own Bootstrap CCS files.
Suppose you have downloaded the Bootstrap theme file, it will contain the main CCS file called bootstrap.min.css. Put this file to your static folder. Then overwrite the styles macro in your base template to include it:
{% extends 'bootstrap/base.html' %}
{% block styles %}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='path/to/your/bootstrap.min.css')}}">
{% endblock %}
I have some Python in Jupyter notebooks that creates pivot tables and some graphs from data. I now want to make PDF reports from this data and I'm looking at making HTML with Jinja2 and converting that to PDF.
I get that Jinja can have a base template and child templates that inherit from it. What I want is a base template that I can render that pulls HTML in from other files (so the base template doesn't get huge and I can debug smaller pieces).
What's the best way to achieve this?
Good evening,
In your case, what I would do is having a folder with your templates.
For example:
templates
|- base.html
|- my_template.html
|- another_template.html
Include
A solution is to use include:
For example in your base.html you would have:
<html>
<head>
</head>
<body>
{% include ['my_template.html', 'another_template.html'] %}
</body>
</html>
Here we include the results of rendering my_template.html and another_template.html in your base.html template.
You will have to give to your render function all the parameters needed for all the HTML templates you want to render.
Extends
With jinja2 you can also do what you want by using the extends capacity.
So let's say you have a template base.html of the type:
<html>
<head>
</head>
<body>
{% block core %}
{{ content }}
{% endblock %}
</body>
</html>
Here, we have a block named core.
You can then in another template extend the base template and replace the core block by something else, for example:
{% extends "base.html" %}
{% block core %}
<h1>Hello world</h1>
{% endblock %}
Unfortunately as you can see it means that if you want various HTML pieces you will have to do several extends.
You can have another template which is going to extend the previous template which extend the base one.
Manual
The last solution which is in my opinion not recommended, but for the sake of it I will expose it here:
Have a base.html of the kind:
<html>
<head>
</head>
<body>
{% for html in list_html_to_render %}
{{ html }}
{% endfor %}
</body>
</html>
Then we don't use Jinja2 anymore in this case, but we render each html contained in the list_html_to_render passed to the render function.
I hope it helps.
Have a lovely day,
My best regards.
I'm using auto generated HTML which has been saved to a file and then read in again to use as part of a page in a django template.
In order to do this I have used:
{% autoescape off %}
{{ my_html }}
{% endautoescape %}
However, in the my_html variable, I have some static content. This comes in the form of something like this:
<img src="{% static "img/tree_report.png" %}" width="12px" height="12px"/>
My issue is that the static content is not displayed. I get:
http://127.0.0.1:8000/%7B%%20static 404 (in the browser error report)
I read something about get_static_prefix in another question but that doesn't solve my problem because I just get this instead:
GET http://127.0.0.1:8000/%7B%%20get_static_prefix%20%%7Dimg/tree_report.png 404 (Not Found)
I also tried endautoscape turning on and off periodically in my_html in the saved HTML variable. That also didn't work.
Should I be autogenerating the development and production static files paths for my_html or is there a more elegant solution to this problem?
Any suggestions are most welcome.
Thanks.
I'm using Sphinx to document a python project. I'm using the canvas to visualize some results in the documentation. My documentation needs to support Firefox and IE. I need to include the excanvas.js library in the documentation, but only if the browser is IE. How can I conditionally include this library so the relative paths are correct?
Example....
Documentation folders
/sphinx
/source
working_test_page.rst
test_block.html
/nested
non_working_test_page.rst
test_block_copy.html
/_templates
layout.html
/_static
excanvas.js
...
Per the notes at Sphinx' documentation pages, the file layout.html was modified. This modification was to insert a conditional block of HTML in the template head which adds excanvas.js on if the page is viewed on IE.
{% extends "!layout.html" %}
{% block extrahead %}
<!--[if IE]>
<script type="text/javascript" src="_static/excanvas.js"></script>
<![endif]-->
{% endblock %}
The file working_test_page.rst and non_working_test_page.rst have the same contents. The contents follow. The only difference is the location of the files.
Script Test
==========
.. raw:: html
:file: test_block_1.html
The file test_block.html and test_block_copy.html have the same contents. The two files contain a some HTML which sets up a canvas and uses it.
When sphinx compiles the rst files into the HTML build directory, the following files structure results:
/sphinx
/build
working_test_page.html
/nested
non_working_test_page.html
/_static
excanvas.js
...
The file working_test_page.html has the correct path to excanvas.js and loads correctly. The file non_working_test_page.html has the wrong path to excanvas.js and does not load correctly.
How can excanvas.js be conditionally loaded so that the relative paths in the sphinx documentation are correct regardless of the location of the rst files?
The conditional link will be formatted properly if the helper function pathto(...) is used to modify the conditional HTML snipet. See documentation on pathto(file,1).
{% extends "!layout.html" %}
{% block extrahead %}
<!--[if IE]>
<script type="text/javascript" src="{{pathto("_static/excanvas.js", 1)}}"></script>
<![endif]-->
{% endblock %}
I'd like everything to function correctly, except when it's mobile, the entire site will used a set of specific templates.
Also, I'd like to autodetect if it's mobile. If so, then use that set of templates throughout the entire site.
Have two sets of templates, one for mobile, one for desktop. Store the filenames in a pair of dictionaries, and use the User-agent header to detect which set should be used. Also allow manual selection of which site to use via a session entry.
If you place a class on your body (Django uses something similar to specify what column style to use), you could use the same templates but simply use different stylesheets. I'm not sure what main differences you are using separate templates for, but this might allow you to cut down on re-coding the templates multiple times.
best practice: use minidetector to add the extra info to the request, then use django's built in request context to pass it to your templates like so.
from django.shortcuts import render_to_response
from django.template import RequestContext
def my_view_on_mobile_and_desktop(request)
.....
render_to_response('regular_template.html',
{'my vars to template':vars},
context_instance=RequestContext(request))
then in your template you are able to introduce stuff like:
<html>
<head>
{% block head %}
<title>blah</title>
{% if request.mobile %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-mobile.css">
{% else %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-desktop.css">
{% endif %}
</head>
<body>
<div id="navigation">
{% include "_navigation.html" %}
</div>
{% if not request.mobile %}
<div id="sidebar">
<p> sidebar content not fit for mobile </p>
</div>
{% endif %>
<div id="content">
<article>
{% if not request.mobile %}
<aside>
<p> aside content </p>
</aside>
{% endif %}
<p> article content </p>
</aricle>
</div>
</body>
</html>
There are different strategies.
If you've a lot of views that renders to template files for the web version, and don't want to rewrite all views checking if the request is coming from a mobile user-agent, you'd be better writing a Middleware.
A workflow could be like this:
def process request:
if from_mobile:
settings.TEMPLATE_DIRS=settings.TEMPLATE_MOBILE_DIRS
else:
settings.TEMPLATE_DIRS=settings.TEMPLATE_WEB_DIRS
There is only a little problem here: As Django Documentation reports, it's not correct to change settings at runtime: http://docs.djangoproject.com/en/dev/topics/settings/#altering-settings-at-runtime
So you may want to call
django.conf.settings.configure(default_settings, **settings)
The answer depends heavily on the type of your target audience. If you target for modern mobile browsers equivalents to their desktop counterparts (such as WebKit-based), all you need is specific stylesheet with appropriate media query (you are basically designing for low-res rather than mobile).
Totally different strategy is needed if your site (e.g. airline schedules) must to be accessible widest possible range of mobile devices, some of running very old / limited browsers. Then custom (html) templates may be easiest way to go.
You might want to check out mobilesniffer and django-bloom to see if they fit your purposes.