Flaks / Jinja nested if statement - flask

I am stuck on a nested if statement, thinking I am approaching it wrong. I have a list of about 100 products that I am rendering on my page. I want to have a nested 'if' statement. Users will have a toolkit, and if the product is in their toolkit, i want to render "Already Uses", else "Add to toolkit?"
{% for product in products|sort(attribute="name") %}
{{ product.name }}
{% for products in toolkit %}
{% if product.name in toolkit %}
<p>Already Uses<p>
{% else %}
<p>Add to toolkit?<p>
{% endif %}
{% endfor %}

more details on: jinja2 check if value exists in list of dictionaries
You are spot on and on the right path. It would help to provide the structure (as an example) of the product object ...
{% for product in products|sort(attribute="name") %}
{{ product.name }}
{% if product.name in toolkit %}
<p>Already Uses<p>
{% else %}
<p>Add to toolkit?<p>
{% endif %}
{% endfor %}
If toolkit is a nested map map:
{% if product.name in toolkit|map(attribute="<whatever has the value equal with product.name>") %}
<p>Already Uses<p>
{% else %}
<p>Add to toolkit?<p>
{% endif %}

Related

How to display N number of Backward relationship in Django templates?

{% for category in categories %}
{% for product in categories.product_set.all %}
<h1> {{ product.name }} </h1>
{% endfor %}
{% endfor %}
I want to show 10 products instead of all in template
There is a slice filter that you can use in templates:
{% for category in categories %}
{% for product in categories.product_set.all|slice:":10" %}
<h1> {{ product.name }} </h1>
{% endfor %}
{% endfor %}

Examine cart in Shopify

I'm hoping for some help with liquid in Shopify, I'm having trouble with trying to customise the cart based on what product the customer has added.
Basically if a customer adds product from Vendor A then I want the cart to load the template to customise the cart for Vendor A
But if product is from Vendor B then I want it to load the template to customise the cart for Vendor B
But if the cart has products from neither (or both) then I want it to load the default cart.
{Edit: I worked out what was wrong with my code to load the templates but now I just need help with the logic so that when the cart has products from both brands it loads the default cart. Because at the moment it loads both cart snippets into the page}
Any help massively appreciated!
{% for item in cart.items %}
{% if item.vendor == 'Brand A' %}
{% include 'cart-a' %}
{% elsif item.vendor == 'Brand B' %}
{% include 'cart-b' %}
{% else %}
{% section 'cart-default %}
{% endif %}
{% endfor %}
also tried this:
{% case cart.items %}
{% when item.vendor == 'Brand A' %}
{% include 'cart-a' %}
{% when item.vendor == 'Brand B' %}
{% include 'cart-b' %}
{% when item.vendor == ‘Brand A’ and item.vendor == 'Brand B' %}
{% section 'cart-default' %}
{% else %}
{% section 'cart-default' %}
{% endcase %}
I think this steps may help you...
Step 1: Create different section instead of snippets for two different types of vendors and default
Step 2: Follow the below code in cart.liquid
{% assign vendor = '' %}
{% assign same = true %}
{% for item in cart.items %}
{% if vendor != '' or vendor == item.vendor %}
{% assign vendor = item.vendor %}
{% else%}
{% assign same = false %}
{% endif %}
{% endfor %}
{% if same == true %}
{% if vendor == 'Brand A' %}
{% section 'cart-a' %}
{% elsif vendor == 'Brand B'%}
{% section 'cart-b' %}
{% else %}
{% section 'cart-default' %}
{% endif %}
{% else %}
{% section 'cart-default' %}
{% endif %}
In liquid it is easier to work with arrays. Working code for you:
{% assign vendors = cart.items | map: 'vendor'| uniq | join: ' ' %}
{% if vendors contains "Brand A" and vendors contains "Brand B" %}
{% section 'cart-default' %}
{% else %}
{% if vendors contains "Brand A" %}
{% section 'cart-a' %}
{% else %}
{% if vendors contains "Brand B" %}
{% section 'cart-b' %}
{% else %}
{% section 'cart-default' %}
{% endif %}
{% endif %}
{% endif %}

If statement in my Django template...Is there a better way?

In my Django template: I'm trying to add an extra div around my for loop only if the length of the data being passed to the template is 3. This is what I'm trying right now but it seems like there could be better way than doing two if statements to check for the length:
{% if items|length == 3 %}
<div class='three-item-wrap'>
{% endif %}
{% for item in items %}
.......
{% endfor %}
{% if items|length == 3 %}
</div> //close .three-item-wrap
{% endif %}
you can try like that
{% if items|length == 3 %}
<div class='three-item-wrap'>
{% for item in items %}
.......
{% endfor %}
</div>
{% else %}
#another logic goes here
{% endif %}
if you want know more refer the docs django if tempalate
I think better way would be to make single if statement check. Just like this:
{% if items|length == 3 %}
<div class='three-item-wrap'>
{% for item in items %}
.......
{% endfor %}
</div>
{% else %}
{% for item in items %}
.......
{% endfor %}
{% endif %}
This way is better because of Django render engine, which firstly check if statements and then do for loop.
And if something crash in your code, div will be without closing tag </div>. Instead in my code there is no option for div to be without closing tag.

Django loop – remove last comma

I have the following loop set up, but need to remove the comma on the last item (it's to replicate a JSON array for cycle2)
{% for product_in_series in series.get_products %}{%spaceless%}
{% with product_in_series.product as product %}
{%if not forloop.first%}
"<img src='{% version product.get_overview 'page_image' %}'>",
{%endif%}
{% endwith %}
{%endspaceless%}{% endfor %}
Cheers,
R
What about this?
{% for product_in_series in series.get_products %}{%spaceless%}
{% with product_in_series.product as product %}
{%if not forloop.first%}
"<img src='{% version product.get_overview 'page_image' %}'>"
{%if not forloop.last%},{%endif%}
{%endif%}
{% endwith %}
{%endspaceless%}{% endfor %}
{{ forloop.last|yesno:",,"|safe }}
, - is a comma
None of the above works for me.
The correct syntax, as in Django 3.0, is as such
{% with querythisandthat as A %}
{% for u in A %} {{ u.interesting_stuff }}
{% if u == A.last %} . {% else %} ; {% endif %}
{% endfor %}
{% endwith %}
The reason is that A.last is not True/False, but it is the last element of the queryset
https://docs.djangoproject.com/en/3.0/ref/models/querysets/#django.db.models.query.QuerySet.first

Django template: check for empty query set

Is there a way to check for an empty query set in the Django template? In the example below, I only want the NOTES header to be displayed if there are notes.
If I put an {% empty %} inside the "for" then it does display whatever is inside the empty tag, so it knows it's empty.
I'm hoping for something that does not involve running the query twice.
{% if notes - want something here that works %}
NOTES:
{% for note in notes %}
{{note.text}}
{% endfor %}
{% endif %}
Clarification: the above example "if notes" does not work - it still displays the header even with an empty query set.
Here's a simplified version of the view
sql = "select * from app_notes, app_trips where"
notes = trip_notes.objects.raw(sql,(user_id,))
return render_to_response(template, {"notes":notes},context_instance=RequestContext(request))
Edit: the view select selects from multiple tables.
Have a look at the {% empty %} tag.
Example from the documentation
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athletes in this list.</li>
{% endfor %}
</ul>
Link: https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#for-empty
If you are interested in a table, or some kind of heading if there are results, add the forloop.first:
{% for athlete in athlete_list %}
{% if forloop.first %}
Athlete Name:
{% endif %}
{{ athlete.name }}
{% empty %}
Sorry, no athletes in this list.
{% endfor %}
Try {% if notes.all %}. It works for me.
In your view check whether notes is empty or not. If it is then you pass None instead:
{"notes": None}
In your template you use {% if notes %} as normal.
It's unfortunate that you're stuck using a raw query set - they're missing a lot of useful behavior.
You could convert the raw query set into a list in the view:
notes_as_list = list(notes)
return render_to_response(template, {"notes":notes_as_list},context_instance=RequestContext(request))
Then check it as a boolean in the template:
{% if notes %}
Header
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
You could also make it happen without conversions using forloop.first:
{% for note in notes %}
{% if forloop.first %}
Header
{% endif %}
{{ note.text }}
{% endfor %}
What about:
{% if notes != None %}
{% if notes %}
NOTES:
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
{% else %}
NO NOTES AT ALL
{% endif %}
Your original solution
{% if notes %}
Header
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
Works now with Django 1.7 and thanks to QuerySet caching, it does not cost and extra query.
Often the right way to do this is to use the {% with ... %} tag. This caches the query so it runs only once and also gives you more flexibility with your markup than using {% empty %}.
{% with notes as my_notes %}
{% if my_notes %}
<ul>
{% for note in my_notes %}
<li>{{ note }}</li>
{% endfor %}
</ul>
{% else %}
<p>Sorry, no notes available</p>
{% endif %}
{% endwith %}
With this particular example I'm not sure how useful it is but if you're querying Many-to-Many field, for instance, it's likely what you want to do.
Use {% empty %} in django templates
{% if list_data %}
{% for data in list_data %}
{{ data.field_1 }}
{% endfor %}
{% else %}
<p>No data found!</p>
{% endif %}
We can write above code with {% empty %}.
{% for data in list_data %}
{{ data.field_1 }}
{% empty %}
<p>No data found!</p>
{% endfor %}