How do I retain the whitespace in templates' blocks? - django

I'm using SHPAML (HAML for python) for Django, however, I'm facing problems converting SHPAML -> HTML because of whitespace issues when overriding some blocks, heres an example:
In skeleton.shpaml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{{ title }}</title>
{% comment %}
<link rel="shortcut icon" href="/static/images/favicon.ico" type="image/x-icon"/>
{% endcomment %}
{% if css_list %}
{% for css in css_list %}
<link type="text/css" rel="stylesheet" href="{{css_relative}}{{ css }}">
{% endfor %}
{% endif %}
{% if js_list %}
{% for js in js_list %}
<script type="text/javascript" src="{{js_relative}}{{ js }}">
</script>
{% endfor %}
{% endif %}
{% if no_cache %}
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache" />
{% endif %}
</head>
body
#nonFooter
#content
{% block header %} {% endblock %}
#maincontent
{% block content %} {% endblock %}
#footer
</html>
In index.shpaml:
{% extends "includes/skeleton.shpaml" %}
{% block content %}
asd
.test
.test2 | meh
{% endblock %}
In the end, my output is this:
!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Home | Zineified</title>
<link type="text/css" rel="stylesheet" href="/media/css/base.css">
<script type="text/javascript" src="/media/js/jquery-1.3.2.min.js">
</script>
<script type="text/javascript" src="/media/js/jquery.form.js">
</script>
<script type="text/javascript" src="/media/js/base.js">
</script>
</head>
body
#nonFooter
#content
#maincontent
asd
.test
.test2 | meh
#footer
</html>
As you can see, whitespace is not preserved in the blocks. The next line in index.shpaml goes straight down into the next line in skeleton.shpaml. How can I prevent this and retain whitespace through template extending?

It looks like the SHPAML preprocessor is not getting invoked BEFORE Django. What I typically do is write all my documents in SHPAML with a .shpaml extension, and then I convert them to Django with the .html extension, and then let Django do its magic. So you will want statements like "extends" and "include" to refer to the .html document that has already been preprocessed.
Your base shpaml doc will look something like this:
html
body
#main_page
{% block body %}
{% endblock %}
And then the document that extends it will look something like this:
{% extends 'base.html' %}
{% block body %}
p
This is a paragraph about {{ book }}...
{% endblock %}
And then you want to preprocess them BEFORE Django sees them. I usually preprocess them with a Python script right before doing "manage.py runserver."

from docs:
spaceless
Removes whitespace between HTML tags. This includes tab characters and newlines.
Example usage:
{% spaceless %}
<p>
Foo
</p>
{% endspaceless %}
This example would return this HTML:
<p>Foo</p>
Only space between tags is removed -- not space between tags and text.
You can also remove excess spaces/newlines manually, but that will reduce the readability of the template.

#maincontent
asd
You mean misalignment here? Well, align your index.shpaml accordingly:
{% extends "includes/skeleton.shpaml" %}
{% block content %}
asd
.test
.test2 | meh
{% endblock %}

I've wrote a simple script to recursively explore a directory and find all shpaml files and convert them to *.htm. Thought I'd share it:
#!/usr/bin/env python
#===============================================================================
# Recursively explore this entire directory,
# and convert all *.shpaml files to *.htm files.
#===============================================================================
import shpaml
import os, glob
count = 0
def main():
global count
cwd = os.path.dirname(os.path.abspath(__file__))
convert_and_iterate(cwd)
print("Done. Converted "+str(count)+" SHPAML files.")
def convert_and_iterate(path):
global count
for file in glob.glob(os.path.join(path,'*.shpaml')):
#getting generic name
file_basename = os.path.basename(file)
gen_name = os.path.splitext(file_basename)[0]
#opening shpaml file and converting to html
shpaml_file = open(file)
shpaml_content = shpaml_file.read()
html_content = shpaml.convert_text(shpaml_content)
#writing to *.htm
html_file = open(os.path.join(path,gen_name+".htm"),"w")
html_file.write(html_content)
#incrementing count
count += 1
#transverse into deeper directories
dir_list = os.listdir(path)
for possible_dir in dir_list:
if os.path.isdir(os.path.join(path,possible_dir)):
convert_and_iterate(os.path.join(path,possible_dir))
if __name__ == "__main__":
main()

Related

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)

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.

Django - Show plot from SQLite database, accessed by form

So I have a page written using Django where someone can enter information into a form, and on submit it accesses a SQLite database to retrieve the queried information. So far I have gotten this far, but I am not able to create and show a plot below the form on the page.
I have tried different packages: ChartIt, Graphos and nvd3. Either way I get an error, likely because I don't understand the full details of the coding in Django.
Below is my try at creating a plot with nvd3. When I try to load the page I get the error:
Exception Value: Invalid block tag: 'load_chart', expected 'elif', 'else' or 'endif'
at the line in my viewrun.html where I assume I load in the nvd3:
{% load_chart charttype chartdata "linewithfocuschart_container" True "%d %b %Y %H" %}
Here are the files I use. Thank you for any help!
views.py
def createplot(molecules, chemrun_id, database='laminar_idl.test.db'):
conn, status_db = conn_to_db(database)
if status_db and not molecules==None:
time, x, y, abunds, status_fetch = get_one_species_all_times(conn, str(molecules))
chartdata = {'x': time,
'name1': molecules, 'y1': abunds}
charttype = "lineWithFocusChart"
data = {
'charttype': charttype,
'chartdata': chartdata
}
return data
return None
#login_required
def run(request, chemrun_id=1, molecule=None):
if request.POST:
form = MolChoiceForm(request.POST)
if form.is_valid():
form.save()
molecule = form.cleaned_data['molecule']
return HttpResponseRedirect('/chemrun/run/'+chemrun_id+'/'+molecule+'/')
else:
form = MolChoiceForm()
args = {}
args.update(csrf(request))
args['form'] = form
args['chemrun'] = ChemRun.objects.get(id=chemrun_id)
if not molecule is None:
args['molecule'] = molecule
plotdata = createplot(molecule, chemrun_id)
args['plotdata'] = plotdata
return render_to_response('interface/viewrun.html', args, context_instance=RequestContext(request))
viewrun.html:
{% extends "interface/base.html" %}
{% block content %}
<article>
{% if user.is_authenticated %}
<header>
<p><font size="+2">Chemical run: <i>{{run.title}}</i> (<b>ID #{{chemrun.id}}</b>)</font></p>
{% load_chart charttype chartdata "linewithfocuschart_container" True "%d %b %Y %H" %}
</header>
<section>
<p>Outputs written for {{chemrun.n_times}} time steps between {{chemrun.times_min}} and {{chemrun.times_max}} years</p>
<p>Temperature: <b>{{chemrun.temperature}}</p>
<p>Density: <b>{{chemrun.density}}</p>
<hr>
<form action='/chemrun/run/{{chemrun.id}}/' method='post' style="display: inline-block;">{% csrf_token %}
{{form}}
<input type="submit" name="submit" value="Plot">
</form>
</section>
{% else %}
<h2>No data available because you are not logged in.
{% endif %}
{% endblock %}
base.html:
{% load staticfiles %}
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<link rel="stylesheet" href="{% static 'css/normalize.min.css' %}">
<link rel="stylesheet" href="{% static 'css/main.css' %}">
<link media="all" href="{% static 'nvd3/src/nv.d3.css' %}" type="text/css" rel="stylesheet" />
<script type="text/javascript" src='{% static 'd3/d3.min.js' %}'></script>
<script type="text/javascript" src='{% static 'nvd3/nv.d3.min.js' %}'></script>
<!--<script src="js/vendor/modernizr-2.8.3-respond-1.4.2.min.js"></script>-->
<title>Chemicalizer</title>
</head>
<body>
<div class="header-container">
<header class="wrapper clearfix">
<h1 class="title"><b><a href='/'>Chemicalizer</a></b> </h1>
<!--<h2 class="subtitle">- You need it!</h2>-->
<nav>
<ul>
{% if user.is_authenticated %}
{% if user.is_superuser %}
<li>Admin</li>
<li>All Models</li>
{% else %}
<li>Start model</li>
<li>My Models</li>
{% endif %}
<li>Logout</li>
{% else %}
<li>Login</li>
<li>Register</li>
<li>Contact</li>
{% endif %}
</ul>
</nav>
</header>
</div>
<div class="main-container">
<div class="main wrapper clearfix">
{% block content %}
{% endblock %}
</div> <!-- #main -->
</div> <!-- #main-container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.11.2.min.js"><\/script>')</script>
<!--<script src="js/main.js"></script>-->
</body>
</html>
For people in the future fighting the same problem, I was using pages that did not explain all steps for getting nvd3 to work (or they were maybe outdated).
Here are the steps to follow to install it and get it working:
1) Install django-nvd3 using pip install django-nvd3
2) Since this is dependent on python-nvd3, we need to install bower using npm install -g bower. (If you don't have npm, just install it with macports, or any other way you like.)
3) Next, install django-bower with the command pip install django-bower
4) Then run bower install nvd3 which will also install the dependency d3
5) Edit your view.py to something like this, this example is for a lineChart:
charttype = "lineChart"
chartcontainer = 'linechart_container' # container name
data = {
'charttype': charttype,
'chartdata': chartdata,
'chartcontainer': chartcontainer,
'extra': {
'x_is_date': False,
'x_axis_format': '',
'tag_script_js': True,
'jquery_on_ready': True,
'chart_attr': {
'xScale':'(d3.scale.log())', #for logscale on x-axis
'yScale':'(d3.scale.log())', #for logscale on y-axis
'xAxis.axisLabel':'"Time, yrs"',
'yAxis.axisLabel':'"n(X)/n(H)"',
}
}
}
return data
6) Update your settings.py with the following:
BOWER_COMPONENTS_ROOT = BASE_DIR
BOWER_PATH = '/usr/local/bin/bower'
BOWER_INSTALLED_APPS = (
'd3',
'nvd3',
)
and also add 'djangobower.finders.BowerFinder', to your STATICFILES_FINDERS = (
7) Now your html code has to include these (in the head for example):
<link media="all" href="{% static 'nvd3/src/nv.d3.css' %}" type="text/css" rel="stylesheet" />
<script type="text/javascript" src='{% static 'd3/d3.min.js' %}'></script>
<script type="text/javascript" src='{% static 'nvd3/nv.d3.min.js' %}'></script>
And somewhere in your main body:
{% include_chart_jscss %}
{% load_chart charttype chartdata chartcontainer extra %}
Finally, for wherever you want the plot to appear:
{% include_container chartcontainer %}
This worked for me. If anyone more knowledgeable about this finds any mistakes, please help me correct them :)

How to call several addOnLoad functions in dojo?

I'm trying to define several dojo elements from several (inherited) HTML pages , and each defines addOnLoad of his own, which causes only the latest function to be executed, since they are overridden.
Is there a way to overcome this problem?
Thanks.
You can use blocks to replace inherited elements
in template-base:
<head>
<script type="text/javascript" src=""></script>
{% block extra-header %}
#code default
...
{% endblock %}
</head>
in template:
{% block extra-header %}
{{ block.super }}
#replacement code
...
<script type="text/javascript" src=""></script>
{% endblock %}
for more information see https://docs.djangoproject.com/en/1.3/topics/templates/#template-inheritance