Overring menu blocks in Django DTL? - python

I got a navbar that will have four links,
{% block navbar %}
<div id="navbar">
Link 1
Link 2
Link 3
Link 4
</div>
{% endblock %}
A class='current' will define the current active page like
<a href="" class='current'>Link 4</a>
My question, is overriding the block navbar on each of the 4 links the best way to do it in Django template language so that each link will have a corresponding class 'current'?

There are many ways to solve this, the right one depends on your exact project. This being said, the simplest solution that could possibly work is to use the {% with %} tag and {{ block.super }}, ie:
In your base template:
{% block navbar %}
<div id="navbar">
Link 1
Link 2
Link 3
Link 4
</div>
{% endblock %}
And then in the template for the "Link1" page:
{% block navbar %}
{% with current="link1" %}
{{ block.super }}
{% endwith %}
{% endblock %}
etc...

Related

get_children not working. get_descendants does. But i can't use that

I am currently working on the navbar of a project with Django-cms. I am fairly new to this framework and language, so sorry if this is a stupid question.
This has double dropdowns, which respond to user changes in the Django-cms admin interface.
Which works. Sort of.
The problem is that get_children doesn't work (no errors or something, just not detecting children, and showing the 'should be dropdown button' as a non dropdown version), but get_descendants does. But if i use that the content of the second dropdown will be shown again in the first dropdown. So get_children will be perfect, as it will only show the direct descendants, instead of all.
{% load cms_tags menu_tags sekizai_tags staticfiles%}
{% load menu_tags %}
{% for child in children %}
<!--non dropdown 1-->
{% if child.is_leaf_node %}
<li>{{child.get_menu_title }}</li>
{% endif %}
<!--dropdown 1-->
{% if not child.is_leaf_node or child.ancestor %}
<div class="dropdown">
<li>{{child.get_menu_title }}<b class="caret"></b></li>
<!-- dropdown 1 content-->
{% if child.get_descendants %}
<div class="dropdown-content">
{% for kid in child.get_descendants %}
<!--non dropdown 2-->
{% if kid.is_leaf_node %}
<li>{{kid.get_menu_title }}</li>
{% endif %}
<!--dropdown 2 -->
{% if not child.is_leaf_node or child.ancestor %}
<li>
<a class="menu-has-sub">{{kid.get_menu_title }}<i class="fa fa-angle-down"></i></a>
<!-- dropdown 2 content-->
<ul class="sub-dropdown droppeddown">
{% for baby in kid.get_descendants %}
<li>{{baby.get_menu_title }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% endif %}
{% endfor %}
So my question is: Why can't i use children
EDIT: *Why can't i use get_children. As in the function. No child labour here.
Nvm i fixed it! The syntax in this case should be children instead of get_children. which is funny because of that edit above.
Anyway, here's an example:
This doesn't work:
{% for kid in child.get_children %}
This does work:
{% for kid in child.children%}
hopefully this will help anyone else having this little struggle.

How can you create multiple menus with django-cms

I'm trying to have two separate menus in my django-cms app. One for the header and another with a different set of links for the footer:
[ Logo ] Link_A Link_B Link_C Link_D
... content ...
Link_E Link_F Link_G Link_H
Using baked in {% show_menu %}, will show all of the pages registered, links A - H, and doesn't allow me to separate the two menus.
How can I create two separate menus?
Depends what you want to do really, but I've got a base template which has a navigation menu at the top and a sitemap submenu at the bottom.
So starting with the navigation;
{% show_menu 1 100 100 100 "partials/navigation.html" %}
Which uses the template;
{% load cms_tags menu_tags cache cms_page %}
{% for child in children %}
<li>
<a href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">
{{ child.get_menu_title }}
</a>
{% if child.children and child.level <= 4 %}
<ul>
{% show_menu from_level to_level extra_inactive extra_active template '' '' child %}
</ul>
{% endif %}
</li>
{% endfor %}
Then the sitemap;
{% show_sub_menu 2 1 1 "partials/sitemap.html" %}
And sitemap.html
{% load cms_tags cms_page cache %}
{% if children %}
{% for child in children %}
<ul class="site-footer__column">
<li>
<h4>
<a href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">
{{ child.get_menu_title }}
</a>
</h4>
</li>
{% if child.children %}
{% for baby in child.children %}
<li class="footer_sub">
<a href="{{ baby.attr.redirect_url|default:baby.get_absolute_url }}">
{{ baby.get_menu_title }}
</a>
</li>
{% endfor %}
{% endif %}
</ul>
{% endfor %}
{% endif %}
Understanding the options (numbers) you can provide for a menu can enable you to display different parts of your site, but if the built in menu tags don't suit your needs, you could write a custom menu tag.
The standard menu docs are here; http://docs.django-cms.org/en/3.2.2/reference/navigation.html
And here are the docs for customising your menus; http://docs.django-cms.org/en/3.2.2/how_to/menus.html

Simplifying the compound extends

On my homepage, I would like to use other pages I have defined as sections. After my navigation, I have a portion for news and team members that run as stand alone pages on my site. It looks something like this:
Header
Nav
<div class="content">
{% include 'news.html' %}
{% include 'officers.html' %}
</div>
Footer
So my news has some basic html but in order not to clone my headers and nav I have to add this line:
{% if page_data.current_page == 'news' %} {% extends "base.html" %} {% endif %}
Is there a way to simplify this statement?
An alternative way to deal with the issue is to move the body of news.html into a partial, for example partials/news.html and then include it in both your home page and in the news page itself:
{# home.html #}
Header
Nav
<div class="content">
{% include 'partials/news.html' %}
{% include 'officers.html' %}
</div>
Footer
and then in news.html:
{% extends "base.html" %}
{% block where_news_belongs %}
{{ super() }} {# if we need to include the contents of the block #}
{% include 'partials/news.html %}
{% endblock where_news_belongs %}

Django-cms show menu: How to show menu under current page?

I'm totally confused by django-cms's show_menu tag. There are four parameters but no full document on these parameters could be found. There are only several exmaples however I cannot find how to show menu under current page only.
Pages are arranged like this:
--Projects
----proj1
----proj2
--Gallery
----gal1
----gal2
In Projects template, how do I set the parameters for show_menu to show only the menu under current page?
Update
#Brandon
I tried exactly this:
{% show_sub_menu 1 "menu/cust_menu.html" %}
As exactly what the document says. However it ends up in this error:
u'menu/cust_menu.html' could not be converted to Integer
You need to use:
{% show_sub_menu 1 %}
http://django-cms.readthedocs.org/en/2.1.3/advanced/templatetags.html#show-sub-menu
There is actually an error in documentation and it seems to be also a little bug introduced in one of the last versions of django cms (planned to be solved in django-cms 3.0 version!).
https://github.com/divio/django-cms/issues/1913
I solved using this:
{% show_menu_below_id "topics_page" 0 4 100 100 "./_menus/menu_topics.html" %}
where "topics_page" is the reverse id (you configure it in advanced section in cms admin).
For recursive rendering of menu, just configure the custom id of subpages for which you want display the next menu level;
in your custom menu template, you can play with child properties and the for loop counter. Below, check a nasty example but still useful if you want to customize your menu template:
{% load menu_tags %}
{% load template_extras %}
{% for child in children %}
{# sub voices topics #}
{% if child.level == 1 %}
{% if not forloop.counter|divisibleby:2 %}
<div class="row-fluid">
{% endif %}
<div class="span6">
<div class="sub1">
<a href="{{ child.attr.redirect_url|default:child.get_absolute_url }}"><span
class="icon-play"></span>{{ child.get_menu_title|capfirst }}</a>
</div>
{% if child.children %}
{% show_menu_below_id child.attr.reverse_id 0 4 100 100 template %}
{% endif %}
</div>
{% if forloop.counter|divisibleby:2 %}
</div> <!-- end row fluid -->
{% endif %}
{% elif child.level == 2 %}
{# 2 - {{ child.attr.reverse_id}} - {{ child.get_menu_title }}#}
<div class="row-fluid">
<div class="span11 offset1">
<div class="sub2">
<a href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">{{ child.get_menu_title|capfirst }}
</a></div>
</div>
</div>
{% if child.children %}
{% show_menu_below_id child.attr.reverse_id 0 4 100 100 template %}
{% endif %}
{% elif child.level == 3 %}
{# leaf node topics #}
{# 3 - {{ child.attr.reverse_id}} - {{ child.get_menu_title }}#}
<div class="row-fluid">
<div class="span10 offset2">
<div class="sub3"><a href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">
<i class="icon-list-alt"></i> {{ child.get_menu_title|capfirst }}</a></div>
</div>
</div>
{% endif %}
{% endfor %}

Displaying Page Numbers with django-tables2

I'm currently displaying a dataset using django-tables2.
The docs make no mention of this in particular, so I'm guessing this'll take probably some table overriding - but, I'm hopeful someone out there has already accomplished this.
How can I render page numbers using django-tables2 below my table? What I'd like to be able to display is a horizontal list of page numbers that the user can click.
Thanks in advance.
you need to create a custom page rendering template - you don't need to override any classses.
To do that, start by copying the file
PYTHON\Lib\site-packages\django_tables2\templates\django_tables2\table.html
to the templates directory inside your django application and rename it to mytable.html or whatever else you like.
Now, you need to change the pagination block of that file. There are many ways to do what you like, but a simple way is to add the following lines inside the pagination block (you may remove or keep the other things that are there depending on your specific needs):
{% block pagination.allpages %}
{% for p in table.paginator.page_range %}
{{ p }}
{% endfor %}
{% endblock pagination.allpages %}
Finally, to use your template, just pass your custom template name to the render_table command:
{% load render_table from django_tables2 %}
...
{% render_table table "mytable.html" %}
This is very simple and will give you trouble if you have many pages (so you have to use some ifs to check the number of pages through the table.paginator.num_pages variable). Also, you may highlight the current page and disable the link by using the table.page.number variable.
The above are left as an excersise to the reader :)
Improving on #Serafeim answer (or solving the exercise he left): Here is a pagination block which, using only Django template syntax, renders page numbers that:
are enclosed in a <ul> HTML block, whith CSS classes that "play well" with Bootstrap;
if there are more than 8 pages, at most 3 pages below and above current page are shown;
first and last pages are always shown, with ellipsis between them and the start or end of the range (if needed).
{% with current_page=table.page.number page_count=table.paginator.num_pages rows_per_page=table.page.object_list|length total_rows=table.page.paginator.count %}
{% block pagination %}
<ul class="pagination">
{% block pagination.allpages %}
<li class="current">
{% blocktrans %}Page {% endblocktrans %}
</li>
{% for page in table.paginator.page_range %}
{% with range_start=current_page|add:"-3" range_end=current_page|add:"3" page_count_minus_5=page_count|add:"-5" page_count_minus_1=page_count|add:"-1" %}
{% if page == current_page %}
<li class="active">
<span>{{ page }}</span>
</li>
{% elif page == 1 or page >= range_start and page <= range_end or page == page_count %}
<li class="next">
{{ page }}
</li>
{% endif %}
{% if page == 1 and current_page > 5 or page == page_count_minus_1 and current_page <= page_count_minus_5 %}
<li class="current">...</li>
{% endif %}
{% endwith %}
{% endfor %}
{% endblock pagination.allpages %}
{% block pagination.cardinality %}
<li class="cardinality">
{% if total_rows != rows_per_page %}{% blocktrans %}
{{ rows_per_page }} of {{ total_rows }}{% endblocktrans %}
{% else %}
{{ total_rows }}
{% endif %}
{% if total_rows == 1 %}
{{ table.data.verbose_name }}
{% else %}
{{ table.data.verbose_name_plural }}
{% endif %}
</li>
{% endblock pagination.cardinality %}
</ul>
{% endblock pagination %}
{% endwith %}
Pagination is introduced in version# >= 2.0.0
https://django-tables2.readthedocs.io/en/latest/pages/CHANGELOG.html
Simply add following code in settings.py. Pagination with number will be rendered with bootstap 4 style. Make sure you have bootstrap 4 reference in html template.
DJANGO_TABLES2_TEMPLATE = 'django_tables2/bootstrap4.html'
And check out more styles in documentation.
https://django-tables2.readthedocs.io/en/latest/pages/custom-rendering.html#available-templates

Categories

Resources