Programming
1. Base html
{% extends "base.html" %}{% load static %}
{% comment %}
This extends YOUR project template at templates/base.html.
Adjust the three block names below to match yours. Django project bases
commonly use one of:
title | page_title
extra_head | extra_css | head
content | main | body_content
extra_js | scripts | extra_scripts
If your base has no head/js blocks, see the note at the bottom of this file.
If you would rather the dashboard stand on its own page, change the first
line to {% extends "portfolio/base_standalone.html" %} and delete the
extra_head / extra_js blocks — the standalone base carries them already.
Everything is wrapped in <div class="lb"> and the stylesheet is scoped to it,
so nothing here can leak into the rest of your site.
{% endcomment %}
{% block title %}{{ t.report_title }} — {{ period_label }}{% endblock %}
{% block extra_head %}
{# Plotly loads once here. Every figure uses include_plotlyjs=False. #}
<script src="https://cdn.plot.ly/plotly-2.35.2.min.js" charset="utf-8"></script>
<link rel="stylesheet" href="{% static 'portfolio/portfolio.css' %}">
<style>
.lb{
--ink:{{ brand.ink }}; --ink-soft:{{ brand.ink_soft }};
--gold:{{ brand.gold }}; --gold-deep:{{ brand.gold_deep }};
--paper:{{ brand.paper }}; --rule:{{ brand.rule }}; --muted:{{ brand.muted }};
--bad:{{ brand.bad }}; --good:{{ brand.good }};
--font-display:{{ brand.font_display }};
--font-body:{{ brand.font_body }};
--font-mono:{{ brand.font_mono }};
}
</style>
{% endblock %}
{% block content %}
<div class="lb">
<div class="lb-header">
<div class="lb-wrap lb-bar">
<div class="lb-brand">
<span class="lb-mark"></span>
<span class="lb-name">{{ t.report_title }}</span>
</div>
<form method="get" class="lb-controls">
<label>
<span>{% if lang == 'ru' %}Период{% else %}Period{% endif %}</span>
<select name="period" onchange="this.form.submit()">
{% for p in periods %}
<option value="{{ p.value }}" {% if p.value == period %}selected{% endif %}>{{ p.label }}</option>
{% endfor %}
</select>
</label>
<label>
<span>{% if lang == 'ru' %}Язык{% else %}Language{% endif %}</span>
<select name="lang" onchange="this.form.submit()">
<option value="ru" {% if lang == 'ru' %}selected{% endif %}>Русский</option>
<option value="en" {% if lang == 'en' %}selected{% endif %}>English</option>
</select>
</label>
<label>
<span>{% if lang == 'ru' %}Курс{% else %}FX{% endif %}</span>
<select name="fx" onchange="this.form.submit()">
<option value="nominal" {% if spec.fx_mode == 'nominal' %}selected{% endif %}>{% if lang == 'ru' %}Номинал{% else %}Nominal{% endif %}</option>
<option value="constant" {% if spec.fx_mode == 'constant' %}selected{% endif %}>{% if lang == 'ru' %}Постоянный{% else %}Constant{% endif %}</option>
</select>
</label>
{% if last_report %}
<a class="lb-btn" href="{% url 'portfolio:report' last_report.period lang %}"
target="_blank" rel="noopener">{% if lang == 'ru' %}Отчёт{% else %}Report{% endif %}</a>
{% endif %}
</form>
</div>
</div>
{% block loanbook_content %}{% endblock %}
</div>
{% endblock %}
{% block extra_js %}
<script>
(function () {
const relayout = () => document.querySelectorAll('.lb .js-plotly-plot')
.forEach(el => window.Plotly && Plotly.Plots.resize(el));
window.addEventListener('resize', relayout);
window.addEventListener('load', relayout);
window.loanbookRelayout = relayout;
})();
</script>
{% block loanbook_scripts %}{% endblock %}
{% endblock %}
{% comment %}
NO HEAD OR JS BLOCK IN YOUR BASE?
Add them — it takes one minute and every future app benefits:
<head>
...
{% block extra_head %}{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
...
{% block extra_js %}{% endblock %}
</body>
If you truly cannot touch it, move the <script> and <link> tags from
extra_head to the top of {% block content %}. Browsers accept it and Plotly
will still load before the figures run, but you lose parallel fetching.
{% endcomment %}
PO
powerty
Author
· Staff
Aug. 26, 2026
Aug. 26, 2026
1
Views
0
Likes
3m
Read