Examine cart in Shopify - if-statement

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

Related

Django: Count forloop.first only if a second if condition is met

I have the following (oversimplified example):
{% for item in myitems %}
{% if item == "orange" %}
{{item}}
{% endif %}
{% endfor %}
Let's say that my list myitems is ['apple','orange','watermelon','orange']. The above code prints twice "orange". But I don't want this... I would like to print it once. So then I tried using if forloop.first
{% for item in myitems %}
{% if item == "orange" %}
{% if forloop.first %}
{{item}}
{% endif %}
{% endif %}
{% endfor %}
The first loop will be item=apple so it won't print the item because it is not "orange". In the second loop now we have item=orange but it no longer fulfills if forloop.first as it is the second loop already so it won't print the item. How can I print orange once? Is there a statement such us: if forloop.first (start numbering from the first print)
I think you can print the element of myitems only once when condition is met using a variable in the template and changing its value when the condition is met:
{% set stop_loop="" %}
{% for item in myitems %}
{% if stop_loop %}
{% elif item == "orange" %}
{{item}}
{% set stop_loop="true" %}
{% endif %}
{% endfor %}
IMO, this kind of business logics should be in the view rather than template.
If I've correctly understood, you're basically looking for this piece of code:
{% for item in myitems %}
{% if item == "orange" and forloop.first %}
{{item}}
{% endif %}
{% endfor %}
A simple and should do the job. With the example you provided ['apple','orange','watermelon'], the rendered template would be blank.
This is my solution based on previous comments
{% with False as stop_loop %}
{% for item in myitems %}
{% if stop_loop %}
{% elif item == "orange" %}
{{item}}
{% update_variable True as stop_loop %}
{% endif %}
{% endfor %}
{% endwith %}
And I need to register in templatetags the following:
#register.simple_tag
def update_variable(value):
return value
It works

Flaks / Jinja nested if statement

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

Multiple condition When statement in Big Cartel

I am trying to make a multiple condition statement on Big Cartel and I keep getting an error telling me that there is an unknown tag in my When statement. I feel like this is very simple. What am I doing wrong? Thank you for looking.
{% case product.status %}
{% when 'sold-out' %}
{% if product.id = '25027747' %}
RESULT 1
{% else %}
{% if product.id = '25027993' %}
RESULT 2
{% else %}
{% endif %}
You'll want to use this code:
{% case product.status %}
{% when 'sold-out' %}
{% if product.id = '25027747' %}
RESULT 1
{% elsif product.id = '25027993' %}
RESULT 2
{% endif %}
{% endcase %}

Removing the logged in user's name from the list of users in django

I have a template that displays the numbers of likes and name of the users liked the forum. But I don't want the request.user's (logged in user's) name in the list, I just want the other user's name and not the user itself. How do I achieve this? And also I want the list of the names in the reverse order in the template (now its showing the latest liked user in the last of the list.). Please guide me. Thank you.
forums.html:
{% extends "base.html" %}
{% load forum_tags %}
{% block content %}
<h2>Logged in as -- {{request.user}}</h2>
<h1>Forums:</h1>
{% if forums.count > 0 %}
{% for forum in forums %}
<h2>{{forum.question}}</h2>
<p>{{forum.body | truncatewords:"30"}}</p>
{% if user in forum.likes.all and forum.likes.count > 1 %}
<p>Unlike You and {{forum.likes.count | substract:1}} others liked</p>
{% elif user in forum.likes.all %}
<p>You liked it</p>
{% else %}
<p>Like</p>
{% endif %}
{% for likes in forum.likes.all %}
<li>{{likes.get_full_name}}</li>
{% endfor %}
{% endfor %}
{% else %}
<p>Sorry! No forum to display.</p>
{% endif %}
{% endblock %}
snippet of views.py:
def forums(request):
forums = Forum.objects.all()
c = {'forums': forums}
return render(request, 'forums.html', c)
Use RequestContext() while passing context to template. It will add user context parameter , then you can compare it in your template as
{% for likes in forum.likes.all %}
{% if user != likes.user %}
<li>{{likes.get_full_name}}</li>
{%endif%}
{% endfor %}
Can you try something like that ?
{% for likes in forum.likes.all %}
{% if user != likes.user %}
<li>{{likes.get_full_name}}</li>
{% endif %}
{% endfor %}
I had to compare it with fullname, as I was displaying the users full name in the list. So, this was the solution:
{% for likes in forum.likes.all.reverse %}
{% if user.get_full_name != likes.get_full_name %}
<li>{{likes.get_full_name}}</li>
{% endif %}
{% endfor %}
Hope this will be helpful to someone as it was for me. And thanks for all those who helped me!

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