Display different <div> depending on arrays length - python

I'm on my first JinJa2 project.
I want to display cars. A car can have one or more options.
If a car has one option, show that. If it has more, hide it for the moment.
Here's my code:
//...
{% set products = ['Audi', 'BMW', 'Mercedes', 'Porsche'] %}
{% set options = ['Small', 'Sport', 'Coupe', 'Jeep'] %}
{% for product in products %}
{% include '../car-product-item.html' with context %}
{% endfor %}
{% if options|length > 1 %}
//If a car has more options, hide this options for the moment
<div class="order-more-options" style="display: none; background: green">
{% for product in options %}
{% include '../car-product-item.html' with context %}
{% endfor %}
</div>
{% elif options|length == 1 %}
//If a car has one option, show this option
<div class="order-more-options" style="display: block; background: orange">
{% for product in options %}
{% include '../car-product-item.html' with context %}
{% endfor %}
</div>
{% endif %}
//...
For some reason its not working. The options are always hidden.
What am I doing wrong?
I checked a Tutorial, the Docu and another SO-Question but nothing helped.

For me it works fine, when I skip the
{% include ...
commands using the following code:
{% set products = ['Audi', 'BMW', 'Mercedes', 'Porsche'] %}
{% set options = ['Small', 'Sport', 'Coupe', 'Jeep'] %}
{% if options|length > 1 %}
<div>more than one options</div>
<div class="order-more-options" style="display: none; background: green">
{% for product in options %}
{{product}}
{% endfor %}
</div>
{% elif options|length == 1 %}
<div>exactly one option</div>
<div class="order-more-options" style="display: block; background: orange">
{% for product in options %}
{{product}}
{% endfor %}
</div>
{% endif %}
Do you use the correct path to car-product-item.html? Try to put the file car-product-item.html to the templates folder and change your include-lines to {% include '/car-product-item.html' ...%}.

Related

Haystack + Django CMS search error "reduce() of empty sequence with no initial value"

I'm relatively new to the Django world. Our client wants to add a search feature to their site so I'm integrating Haystack and Aldryn Search as described here:
https://github.com/aldryn/aldryn-search
I've also gone through here: https://django-haystack.readthedocs.io/en/v2.6.0/tutorial.html
Exception Location: env/lib/python2.7/site-packages/haystack/backends/simple_backend.py in search, line 79
Here are some helpful information snippets:
urls.py -
(r'^search/', include('haystack.urls')),
templates/search/search.html -
{% extends 'base.html' %}
{% block content %}
<div class="primary-content">
<div class="container constrained">
<form method="get" class="paragraph" action=".">
{{ form.as_table }}
<div class="text-right">
<button type="submit" class="button">
Search
</button>
</div>
{% if query %}
<h3>Results</h3>
{% for result in page.object_list %}
<div class="post-preview paragraph">
<h3>
{{ result.object.title }}
</h3>
</div>
{% empty %}
<p>No results found.</p>
{% endfor %}
{% if page.has_previous or page.has_next %}
<div>
{% if page.has_previous %}{% endif %}« Previous{% if page.has_previous %}{% endif %}
|
{% if page.has_next %}{% endif %}Next »{% if page.has_next %}{% endif %}
</div>
{% endif %}
{% else %}
{# Show some example queries to run, maybe query syntax, something else? #}
{% endif %}
</form>
</div>
</div>
{% endblock %}
settings.py -
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
},
}
HAYSTACK_ROUTERS = ['aldryn_search.router.LanguageRouter', ]
ALDRYN_SEARCH_REGISTER_APPHOOK = True
ALDRYN_SEARCH_PAGINATION = 20
ALDRYN_SEARCH_CMS_PAGE = True
Additionally, both 'haystack' and 'aldryn_search' are in INSTALLED_APPS.
When I run update_index --remove it does seem to work for the most part:
Indexing 5 locations
Indexing 2 People
Indexing 16 articles
It looks like I've done everything right according to the documentation. But I must not be. We only have one language on the site so that does make the documentation a little hard to comprehend for me because I'm not sure if I have extra things that are only needed for multi lingual.
Stack trace:
['/build/healthdirect',
'/build/env/lib/python27.zip',
'/build/env/lib/python2.7',
'/build/env/lib/python2.7/plat-darwin',
'/build/env/lib/python2.7/plat-mac',
'/build/env/lib/python2.7/plat-mac/lib-scriptpackages',
'/build/env/lib/python2.7/lib-tk',
'/build/env/lib/python2.7/lib-old',
'/build/env/lib/python2.7/lib-dynload',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
'/build/env/lib/python2.7/site-packages']

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.

Django template if type add to html id

The model gigi has got a typology attribute, I want to add items into a html div tag based on the value of the typology attribute. How can I manage to do this in Djangos templates:
for gigi in object_list
<div id="typology1">
{%if gigi.typology == "typology1"> %}
<div> {{gigi.name}}</div>
{% endif %}
</div>
<div id="typology2">
{%if gigi.typology == "typology2"> %}
<div> {{gigi.name}}</div>
{% endif %}
</div>
Is this the only way? are there better DRY (dont repeat yourself) ways?
There is nothing wrong with the code you currently have; though, you could make the following small adjustment and get rid of quite a bit of code.
Why not use the gigi.typology string as the id?
{% for gigi in object_list %}
<div id="{{ gigi.typology }}">
<div> {{gigi.name}}</div>
</div>
{% endfor %}
If you are looking at having all the elements for a particular "typology" grouped together then you could also use the regroup clause.
{% regoup object_list by typology as typolist %}
{% for typo in typolist %}
<div id="{{ typo.grouper }}">
{% for gigi in typo.list %}
{{ gigi.name }}
{% endfor %}
</div>
{% endfor %}

Does Jinja2 support nested if statements?

I read the docs and I am not clear on this is right at all. I know you can use nested for loops, but if statements seem to be different.
Can i do the following?
{% if thing=true %}
<div> something here</div>
{% if diffthing=true %}
<div> something else</div>
{% else %}
<div> third thing</div>
{% endif %}
{% else %}
<div> nothing here </div>
{% endif %}
Or should the format be different somehow?
Jinja2 supports nested blocks, including if statements and other control structures.
See the documentation on Block Nesting and Scope: "Blocks can be nested for more complex layouts."
A good use case for this is writing macros that conditionally output HTML:
{# A macro that generates a list of errors coming back from wtforms's validate function #}
{% macro form_error_summary(form, li_class='bg-danger') %}
{# only do the following on error... #}
{% if form.errors %}
<ul class="errors">
{# you can do layers of nesting as needed to render your content #}
{% for _field in form %}
{% if _field.errors %}
{% for error in _field.errors %}
<li class={{li_class}}>{{_field.label}}: {{ error|e }}</li>
{% endfor %}
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
The answer is yes.
I'm using logic very similar to yours in a live application and the nested if blocks work as expected. It can get a little confusing if you don't keep your code clean, but it works fine.
It seem possible. Refer to the documentation here: http://jinja.pocoo.org/docs/templates/#if
Just a quick add, if you're unpacking data to populate your fields, Jinja will only unpack it once. I had a similar problem with MongoDB and found if you change the item to a list item you iterate through it more than once without nesting
#app.route("/")
#app.route("/get_shrink")
def get_shrink():
# find and sort shrink top 5
shrink = list(mongo.db.shrinkDB.find().limit(5).sort(
"amount_lost_value", -1,))
return render_template(
"shrink.html", shrinkDB=shrink)
{% for shrink in shrinkDB %}
{% if shrink.resolved == true %}
<li>{{ shrink.product_name }} ||£ {{ shrink.amount_lost_value }} || {{ shrink.date }}</li>
{% endif %}
{% endfor %}
</span>
</div>
</div>
<div class="col s12 m5 offset-m2">
<h4>Top 5 Resolved Threats</h4>
<div class="card-panel light-blue">
<span class="white-text">
<!-- Shrink For loop top 5 resolves-->
{% for shrink in shrinkDB %}
{% if shrink.resolved != true %}
<li>{{ shrink.product_name }} ||£ {{shrink.amount_lost_value }} || {{ shrink.date }}</li>
{% endif %}
{% endfor %}

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 %}

Categories

Resources