Jinja - Using a different css for each extended template - flask

I've come across Flask-Appbuilder as it could solve my problem. I'm trying to load different css for every template where only the skeleton remains the same.
I found this solution https://flask-appbuilder.readthedocs.io/en/latest/templates.html
However it doesn't work. Not for me anyways. I used pip3 install flask-appbuilder and everything went OK. I created appbuilder directory within templates directory. Then I used:
{% extends 'appbuilder/base.html' %}
{% block head_css %}
{{ super() }}
<link rel="stylesheet" href="url_for('static',filename='css/your_css_file.css')}}">
{% endblock %}
what might be causing the problem ? It's like the block head_css is being completely ignored. Only the basic bootstrap css is being loaded.

You can have a single layout.html file extended by all templates, then use if statements to select the correct CSS style sheet for each template by accessing request.endpoint which is basically the view function that renders a template.
{% if request.endpoint == 'index' %}
<link href="{{ url_for('static', filename='main.css') }}" rel="stylesheet" type="text/css">
{% elif request.endpoint == 'another' %}
<link href="{{ url_for('static', filename='another.css') }}" rel="stylesheet" type="text/css">
{% endif %}

Related

django does not load CSS file in HTML-file which extends from "base.html"

I have a base.html which my options.html extends from like this
//options.html
{% extends "webpage/base.html" %}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'webpage/options.css' %}">
{% block content %}
<div class="test">
foo
</div>
{% endblock content %}
//base.html
{% load static %}
<!DOCTYPE html>
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="{% static 'webpage/base.css' %}">
<!-- jQuery-->
<script src="https://code.jquery.com/jquery-3.6.1.slim.js" integrity="sha256-tXm+sa1uzsbFnbXt8GJqsgi2Tw+m4BLGDof6eUPjbtk=" crossorigin="anonymous"></script>
<title>:)</title>
</head>
<body>
hello world
{% block content %}
{% endblock content %}
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
the issue is that the CSS is not loaded/applied.
In the web-console (when I run python manage.py runserver) and go to the "options" page, then I can see that the webpage/base.css is loaded (i.e GET /static/webpage/base.css is printed), but the webpage/options.css is not.
I thought I had something wrong in the static- path, but if I move the
<link rel="stylesheet" type="text/css" href="{% static 'webpage/options.css' %}"> into my base.html(and go to my home page) then I see that GET /static/webpage/options.css is now printet and the css in there indeed takes effect.
Why can it be that it is not loaded in the options.html file? Note, this question is not about CSS changes not taking effect (untill hard-refresh, cache clear etc.) but it seems like the file simply isn't getting loaded
When an HTML file extends another, it needs all its content in blocks, that it can insert into the base.html - otherwise it doesn't know where to put it.
In this case you'd want to create something like
base.html
<head>
...
{% block htmlhead %}
{% endblock htmlhead %}
</head>
And then include that block in your options.html
{% block htmlhead %}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'webpage/options.css' %}">
{% endblock htmlhead %}
According to the Template inheritance documentation, I believe that these three paragraphs explains everything.
All the block tag does is to tell the template engine that a child
template may override those portions of the template.
The extends tag is the key here. It tells the template engine that
this template “extends” another template. When the template system
evaluates this template, first it locates the parent – in this case,
“base.html”.
At that point, the template engine will notice the three block tags in
base.html and replace those blocks with the contents of the child
template.
So basically, when you extend a skeleton, only the parts inside the blocks are replaced, everything else is ignored.
In order to do what you want, you need another block inside your base.html header, and use it in your options.html.

Adjust bootstrap within jinja template (Flask Framework)

I would like to adjust default bootstrap class formatting within jinja template. The only thing, what I want to do, is to change the color of the h1 element. But unfortunately, it is still black.
I am using flask and render_template module.
I have following code in template:
{% extends "bootstrap/base.html" %}
{% block head %}
{{ super() }}
<link rel="stylesheet" type="text/css" href="bootstrap_adjust.css">
{% endblock %}
{% block content %}
<div class="container">
<div class="page-header">
<h1>Hello, Vaclav!</h1>
</div>
</div>
{% endblock %}
boostrap_adjust.css looks like this:
h1{
color:blue;
}
Thank you for any advice!
Vaclav
I ll try to answer the question "how to adjust an element using a .css file instead of styling it directly?"
Go in your base.html file, i.e. the file you extend from, and in the header tag, at the end of all the other stylesheets create a Jinja2 block like so
{% block stylesheets %}
{% endblock stylesheets %}
Second step would be to call this block in your child templates and pass your .css files in there instead of passing it in the head block.
{% block stylesheets %}
<link rel="stylesheet" type="text/css" href="bootstrap_adjust.css">
{% endblock stylesheets %}
Give it a try and let us know!
I finally found working solution here:
https://stackoverflow.com/questions/34664156/flask-bootstrap-custom-theme
So in my case this works:
{% block styles %}
{{ super() }}
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='bootstrap_adjust.css')}}">
{% endblock %}
.css file is placed in the folder static. But be careful, static is not part of the path in filename parameter, because url_for('static') looks automatically in this folder.
Thank you all for your willing to help!
Adding a custom CSS file:
{% block styles %}
{{super()}}
<link rel="stylesheet"
href="{{url_for('.static', filename='mystyle.css')}}">
{% endblock %}
Please Read the documentation on Flask-Bootstrap and have a good understanding of super classes.
This is the Link - Flask-Bootstrap

How to place Bokeh widgets precisely on an html page

I am struggling to place Bokeh widgets precisely where I want them on an html page built with Django. For example my views.py look like this:
from bokeh.io import show
from bokeh.layouts import column, row
from bokeh.models import CustomJS, TextInput
from bokeh.plotting import figure
fig = figure(title='title')
fig.line(x=[1,2,3], y=[1,2,3])
text_input = TextInput(title="Add graph title", value='')
text_input.js_on_change('value', CustomJS(
args={'title': fig.title, 'text_input': text_input},
code="title.text = text_input.value"
))
widgets_layout = column(text_input)
figures_layout = row(fig)
#show(row(widgets_layout, fig))
# Set up page layout
page_layout = row(widgets_layout, figures_layout)
script, div = components(page_layout)
return render_to_response('app/test.html', {'script':script, 'div':div})
and my html page (test.html) look like this:
<!--Test page-->
{% extends "base.html" %}
{% load static %}
{% load bootstrap4 %}
{% load i18n %}
{% block content %}
<!--Bokeh-->
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-1.3.4.min.css" rel="stylesheet" type="text/css">
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.3.4.min.css" rel="stylesheet" type="text/css">
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-tables-1.3.4.min.css" rel="stylesheet" type="text/css">
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-1.3.4.min.js"></script>
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.3.4.min.js"></script>
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-tables-1.3.4.min.js"></script>
<!--Figure-->
<div class='col-lg'>
<div class='card-lg bg-light' id='maincontent'>
<h2> {% trans "Test" %}</h2>
<hr>
<div>
{{ div | safe }}
{{ script | safe }}
</div>
</div>
</div>
<br>
{% endblock content %}
Now, how can I move the little widget (text_input) to a precise position ? Any position will do, I just want to be able to place it pretty much wherever I want.
Thank you,
You could apply for example spacing (which can also be negative) on the Row and/or on the Column like this:
widgets_layout = column(Div(), row(Div(), text_input, spacing=300), spacing=300)

django 1.8 tutorial part 6

First off, I realize Django 1.8 is outdated but I'm required to learn it for a project. I got through the first five parts without any issues but when I try to link the stylesheet in part 6, my stylesheet isn't loading (there's no change in the page).
I've gone over the code several times and checked the namespacing of each folder and it should be working but I can't seem to find the problem. If anyone has gone through this tutorial and could shed some light on the issue, I'd really appreciate it.
Here's the code in mysite/polls/templates/polls/index.html:
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css'
%}" />
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="{% url 'polls:detail' question.id %}">{{
question.question_t\
ext }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
And here's my stylesheet located at mysite/polls/static/polls/style.css:
li a {
color: green;
}
body {
background: white url("images/background.gif") no-repeat right
bottom;
}
For anyone with the same issue, restarting the Django server fixed the problem.

Do I need to use 'load static' twice on overall layout and header in Django?

I'm on a project in Django, and the problem is like this.
My site have a overall layout like 'layout.html' which includes some static files, links in and 'header.html' including navigator, 'footer.html' including some links in . But Both of 'layout.html' and 'header.html' uses static files so I think one command {% load static %} on first line in 'layout.html' can affect both 'layout.html' and 'header.html' because 'layout.html' includes 'header.html'! But it doesn't work, it works only when {% load static %} in both files.
Maybe my explanation is hard to understand, so I will write my code very shortly.
'layout.html'
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<link href="{% static 'onepage-scroll.css' %}" rel="stylesheet" type="text/css">
</head>
<body>
{% include 'header.html' %}
{% block content %}
{% endblock %}
{% include 'footer.html' %}
</body>
</html>
'header.html'
{% load static %}
<nav id="navi">
<h3><img src="{% static 'logo.jpg' %}"></h3>
</nav>
I think this is not a good implementation because there are 2 times of loading staticfiles. Is there another way to solve this?
I think you may be misunderstanding what {% load static %} does. It just gives your template access to the associated {% static %} tag. It does not result in the static files themselves being reloaded or any significant burden in terms of extra code being ported.
You're using the tag exactly as intended. If you need static files, you need to load the tags to do that with.