Can we use multiple rendered queryset in template with multiple for loops in scriptlet in Django framework? - django-templates

I am trying to fetch 2 tables data in a template using the querysets I rendered from my views.py, now I want to fetch both queryset in a template using scriptlet for loop in select field but it is not working. One select field in the template is showing the data but second select field is not showing the data. I tried and find that only one at a time is showing the data while 2nd is not working.
This is my views.py :
def assignWork(request):
man=Coordinator.objects.filter(designation="Manager")
t=Task.objects.all()
return render(request,"MyAdmin/assignWork.html",{"key2":t},{"key1":man})
This is my template assignWork.html in which I am trying to use both.
<form action="assignTask" method="POST">{% csrf_token %}
<label> Tasks</label>
<br>
<select required="">
<option value="">Select</option>
{% if key2 %}
{% for var1 in key2 %}
<option value="{{ var.id}}">
{{ var1.company.cname }}</option>
{% endfor %}
{% endif %}
</select>
<br>
<label> Manager</label>
<br>
<select name=txtname required="">
<option value="">Select Manager</option>
{% if key1 %}
{% for var in key1 %}
<option>
{{ var.name }}</option>
{% endfor %}
{% endif %}
</select>
<b> <- Back</b>
<input type="submit" name="submit" value="Edit Details">
</form>

Related

How to call option.value in the loop of product.variants in Shopify?

I have one hidden dropdown and two variant-selector dropdowns. One dropdown is for color and the second one is for size. I want to add size data in data-size="" and color data in data-color="" in the dropdown of name=id.
<form method="post" action="/cart/add">
{% if product.variants.size > 1 %}
{% for option in product.options_with_values %}
<select class="variant-selector {{option.name}}" data-var="{{forloop.index}}">
{% if product.available %}
{% for values in option.values %}
<option value="{{values}}">{{values}}</option>
{% endfor %}
{% endif %}
</select>
{% endfor %}
<select name="id" style="display:none;" id="data{{forloop.index}}">
{% for variant in product.variants %}
{% if variant.available %}
<option data-size="" data-color="" value="{{ variant.id }}" >{{ variant.title }}</option>
{% endif %}
{% endfor %}
</select>
{% if variant.available%}
<input type="hidden" min="1" type="number" name="quantity" value="1" />
<input type="submit" value="{{ 'products.product.add_to_cart' | t }}" class="btn add-to-cart" />
{% else %}
<input type="submit" value="{{ 'products.product.sold_out' | t }}" class="btn add-to-cart" disabled="disabled">
{% endif %}
{% endif %}
</form>
As Dave B comment I don't need option.value in the loop of product.variants in Shopify. I simply add data-size="{{ variant.option1 }}" and data-color="{{ variant.option2 }}"
<select name="id" style="display:none;" id="data{{forloop.index}}">
{% for variant in product.variants %}
{% if variant.available %}
<option data-size="{{ variant.option1 }}" data-color="{{ variant.option2 }}" value="{{ variant.id }}" >{{ variant.title }}</option>
{% endif %}
{% endfor %}
</select>

Multi file uploader in Shopify Debut theme

I'm customizing my page to upload multiple files (photos). This is the code that I have so far and according to this link it should work:
https://shopify.dev/tutorials/customize-theme-get-customization-information-for-products
in the link go to "Allow file uploads" if you want to check.
{% form 'product', product, class:form_classes, data-product-form: '', enctype:"multipart/form-data" %}
{% unless product.has_only_default_variant %}
<div class="product-form__controls-group">
{% for option in product.options_with_values %}
<div class="selector-wrapper js product-form__item">
<select class="single-option-selector single-option-selector-{{ section.id }} product-form__input"
id="SingleOptionSelector-{{ forloop.index0 }}"
data-index="option{{ forloop.index }}"
>
{% for value in option.values %}
<option value="{{ value | escape }}"{% if option.selected_value == value %} selected="selected"{% endif %}>{{ value }}</option>
{% endfor %}
</select>
</div>
{% endfor %}
</div>
{% endunless %}
<select name="id" id="ProductSelect-{{ section.id }}" class="product-form__variants no-js">
{% for variant in product.variants %}
<option value="{{ variant.id }}"
{%- if variant == current_variant %} selected="selected" {%- endif -%}
>
{{ variant.title }} {%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %}
</option>
{% endfor %}
</select>
{% if section.settings.show_quantity_selector %}
{% comment %}
<div class="product-form__controls-group">
<div class="product-form__item">
<input type="number" id="Quantity-{{ section.id }}"
name="quantity" value="1" min="1" pattern="[0-9]*"
class="product-form__input product-form__input--quantity" data-quantity-input
>
</div>
</div>
<div class="qtydiv">
{% comment %}<label for="Quantity" class="quantity-selector">Quantity</label>{% endcomment %}
<div class="qtybox">
<span class="btnqty qtyminus icon icon-minus">-</span>
<input type="text" id="quantity" name="quantity" value="1" min="1" class="quantity-selector quantity-input" readonly="">
<span class="btnqty qtyplus icon icon-plus">+</span>
</div>
</div>
{% endcomment %}
{% endif %}
<div class="product-form__error-message-wrapper product-form__error-message-wrapper--hidden{% if section.settings.enable_payment_button %} product-form__error-message-wrapper--has-payment-button{% endif %}"
data-error-message-wrapper
role="alert"
>
<span class="visually-hidden">{{ 'general.accessibility.error' | t }} </span>
{% include 'icon-error' %}
<span class="product-form__error-message" data-error-message>{{ 'products.product.quantity_minimum_message' | t }}</span>
</div>
<div class="product-form__controls-group product-form__controls-group--submit">
<div class="qtydiv">
{% comment %}<label for="Quantity" class="quantity-selector">Quantity</label>{% endcomment %}
<div class="qtybox">
<span class="btnqty qtyminus icon icon-minus">-</span>
<input type="text" id="quantity" name="quantity" value="1" min="1" class="quantity-selector quantity-input" readonly="">
<span class="btnqty qtyplus icon icon-plus">+</span>
</div>
</div>
<div class="product-form__item product-form__item--submit
{%- if section.settings.enable_payment_button %} product-form__item--payment-button {%- endif -%}
{%- if product.has_only_default_variant %} product-form__item--no-variants {%- endif -%}"
>
<button type="submit" name="add"
{% unless current_variant.available %} aria-disabled="true"{% endunless %}
aria-label="{% unless current_variant.available %}{{ 'products.product.sold_out' | t }}{% else %}{{ 'products.product.add_to_cart' | t }}{% endunless %}"
class="btn product-form__cart-submit{% if section.settings.enable_payment_button %} btn--secondary-accent{% endif %}"
data-add-to-cart>
<span data-add-to-cart-text>
{% unless current_variant.available %}
{{ 'products.product.sold_out' | t }}
{% else %}
{{ 'products.product.add_to_cart' | t }}
{% endunless %}
</span>
<span class="hide" data-loader>
{% include 'icon-spinner' %}
</span>
</button>
{% if section.settings.enable_payment_button %}
{{ form | payment_button }}
{% endif %}
</div>
<input required class="required product-form__input" id="photo" type="file" name="properties[Photo]" multiple>
</div>
</div>
{% endform %}
This is my form that according to the link must have the attribute
enctype = "multipart / form-data".
At the bottom of the form it is in input type = "file".
<input required class="required product-form__input" id="photo" type="file" name="properties[Photo]" multiple>
And this is the code in the cart-template.liquid.
<div class="list-view-item__title">
<a href="{{ item.url }}" class="cart__product-title" data-cart-item-title>
{{ item.product.title }}<br>
{% assign property_size = item.properties | size %}
{% if property_size > 0 %}
{% for p in item.properties %}
{{ item.properties.count }}
{% assign first_character_in_key = p.first | truncate: 1, '' %}
{% unless p.last == blank or first_character_in_key == '_' %}
{{ p.first }}:
{% if p.last contains '/uploads/' %}
<a class="lightbox" href="{{ p.last }}">{{ property_size }}</a>
{% else %}
{{ p.last }}
{% endif %}
<br>
{% endunless %}
{% endfor %}
{% endif %}
</a>
</div>
The problem is the property_size variable gets value one even if I upload two or more images, when in fact I should return the amount of properties that the item has.
Can anyone help me please? What I am doing wrong?
The Debut theme probably has changed since this tutorial was uploaded, and since it is not supported, probably won't be updated.
If you add a type="text" input instead of a type="file" the property gets added as expected. This happens because the _initAddToCart function (assets/theme.js line 6447) gets the form HTML element and pass it along to another function.
var $data = $(this.selectors.productForm, this.$container);
this._addItemToCart($data);
Then in the _addItemToCart function (assets/theme.js line 6513), the form is serialized to a string:
var params = {
url: '/cart/add.js',
data: $(data).serialize(),
dataType: 'json',
};
$.post(params).done(...
This function will ignore the file inputs, as explained in the jQuery documentation:
Data from file select elements is not serialized.
To send the file, the FormData browser API can be used. But to use it with the jQuery AJAX call, some properties must be set:
var params = {
url: '/cart/add.js',
// data: $(data).serialize(),
dataType: 'json',
// Disable the jQuery data processing, and send the FormData object
contentType: false,
processData: false,
data: new FormData($(data).get()[0])
};
$.post(params).done(...
However, since the HTML file <input> has name="properties[Photo]", only the last of the uploaded files will be added to the cart item's Photo property.
I tried with name="properties[Photo][]", but the cart/add.js call only returns an error 500 with the message "Internal Server Error".
So to upload multiple files you could add some custom code to the _addItemToCart function, to get each File from the <input> and add to the FormData with a different key for each file.

Shopify: Filter by Multiple Tags at Same time

Ok so I am creating menu for filtering products in order to keep my tags and submenu from being extremely long.
I have created a dropdown filter for my main categories (I have added an unless to eliminate sub-level category tags)
I then have a sub-category menu that only shows when "All Categories" isn't selected.
This then generates a sub-category filter for all tags in that category. See below for code:
<div class="text-center">
<div class="browseby" style="display:inline;padding:20px;">
<div class="clearfix filter" style="float:left;">
Browse By Category <select class="coll-filter">
<option value="">All</option>
{% for tag in collection.all_tags %}
{% unless tag == 'HP' or tag == 'Latex' or tag == 'Latex 570' or tag == 'Parts' or tag == 'Aqueous Media' or tag == 'Latex Media' or tag == 'Solvent Media' %}
{% if current_tags contains tag %}
<option value="{{ tag | handle }}" selected>{{ tag }} ({{ collection.products_count }})</option>
{% else %}
<option value="{{ tag | handle }}">{{ tag }}</option>
{% endif %}
{% endunless %}
{% endfor %}
</select>
</div>
{% if current_tags %}
<div class="clearfix filter" style="float:left; padding-left:20px">
Browse By Sub-Category <select class="coll-filter">
<option value="">All</option>
{% for tag in collection.tags %}
{% unless current_tags contains tag %}
{% if current_tags contains tag %}
<option value="{{ tag | handle }}" selected>{{ tag }} ({{ collection.products_count }})</option>
{% else %}
<option value="{{ tag | handle }}">{{ tag }}</option>
{% endif %}
{% endunless %}
{% endfor %}
</select>
</div>
{% else %}
{% endif %}
</div>
Now the problem is when I select the sub-category filter the tag isn't shown as selected.
Browse By Category shows All and then inside the dropdown I have (All, Category1, Category2, Category3..)
If i selected Category3 the page reloads and shows Browse By Category: Category3
Browse By Sub-Category shows All and then inside the dropdown I have (All, SubMenu1, SubMenu2, SubMenu3)
If I select SubMenu2 the products all filter.
Browse By Category still shows: Category3
But Browse By Sub-Category shows: All
Inside the dropdown menu I have (All, SubMenu1, SubMenu3) <-- The category that is being filtered disappears from the list, but does filter products.
If this is confusing let me know.
RESOLVED!!
I found the problem in the above code. The {% unless %} tag in the second filter was causing the problem. The unless was to filter out the main category filter but ended up making the selected option not available. I made my Main Categories start with cat- and the sub-level categories start with sub-
Now the code works mostly... Still having issues when using the sub-category and then filtering back to a main category. The URL keeps the sub-cat and just adds a new main category...
Anyway for those that are interested here is my new code:
<div class="text-center">
<div class="browseby" style="display:inline;padding:20px;">
<div class="clearfix filter" style="float:left;">
Browse By Category <select class="coll-filter">
<option value="">All</option>
{% for tag in collection.all_tags %}
{% if tag contains 'cat-' %}
{% assign tagName = tag | remove: 'cat-' %}
{% if current_tags contains tag %}
<option value="{{ tag | handle }}" selected>{{ tagName }}</option>
{% else %}
<option value="{{ tag | handle }}">{{ tagName }}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>
</div>
<div class="clearfix filter" style="float:left; padding-left:20px">
Browse By Type: <select class="coll-filter">
<option value="">All</option>
{% for tag in collection.tags %}
{% if tag contains 'sub-' %}
{% assign tagName = tag | remove: 'sub-' %}
{% if current_tags contains tag %}
<option value="{{ tag | handle }}" selected>{{ tagName }}</option>
{% else %}
<option value="{{ tag | handle }}">{{ tagName }}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>
</div>
</div>

Shopify - Is it possible to filter by 'Vendor'

it seems Shopify only allows for filtering by tags. If you want to filter by Vendor (which is a standard Shopify Field) you first need to create tags with the same name and manually use those tags in the filter sidebar.
Is this correct? Seems very unnecessary and more importantly makes dynamic updates difficult.
After almost 2 days of trial and error, plus lots of digging into forums and the documentation, I came up with this bit of code to create a working Vendor filter.
Please note the following:
The classes and IDs were created by the Modular Shopify theme. I just reused them, please use the appropriate classes/IDs for your theme.
The Vendor filter does not work with the tag filter or with the sort by option. Those were hidden as explained below.
<div class="grid-filter block">
{% comment %} New Vendor Filter {% endcomment %}
<div class="tag-filter block">
<label for="#vendorFilter">Browse by Vendor</label>
<span class="selectArrow"></span>
<select class="vendorFilter filter" id="vendorFilter" onChange="window.location.href=this.value">
<option value="/collections/all">All</option>
{% for product_vendor in shop.vendors %}
{% if collection.current_vendor contains product_vendor %}
<option value="{{ product_vendor | url_for_vendor }}" selected>{{ product_vendor }}</option>
{% else %}
<option value="{{ product_vendor | url_for_vendor }}">{{ product_vendor }}</option>
{% endif %}
{% endfor %}
</select>
</div>
{% comment %} END New Vendor Filter {% endcomment %}
{% if show_filter == true and collection.current_vendor == blank %}
<div class="tag-filter block">
<label for="#tagFilter">{{ 'collections.tag_filtering.filter_label' | t }}</label>
<span class="selectArrow"></span>
<select class="tagFilter filter" id="tagFilter">
<option value="/collections/{{ collection.handle }}">{{ 'collections.tag_filtering.default_filter' | t }}</option>
{% for tag in collection.all_tags %}
{% if current_tags contains tag %}
<option value="/collections/{{ collection.handle }}/{{ tag | handle }}" selected>{{ tag }}</option>
{% else %}
<option value="/collections/{{ collection.handle }}/{{ tag | handle }}">{{ tag }}</option>
{% endif %}
{% endfor %}
</select>
</div>
{% endif %}
{% if show_sort_filter == true and collection.current_vendor == blank %}
<div class="collectionGrid-filter block">
<label for="#collectionFilter">{{ 'collections.sorting_dropdown.label' | t }}</label>
<span class="selectArrow"></span>
{% assign sort_by = collection.sort_by %}
<select class="filter" id="collectionFilter">
<option value="">{{ 'collections.sorting_dropdown.all' | t }}</option>
<option value="best-selling" {% if sort_by == "best-selling" %}selected{% endif %}>{{ 'collections.sorting_dropdown.best_selling' | t }}</option>
<option value="price-ascending" {% if sort_by == "price-ascending" %}selected{% endif %}>{{ 'collections.sorting_dropdown.price_ascending' | t }}</option>
<option value="price-descending" {% if sort_by == "price-descending" %}selected{% endif %}>{{ 'collections.sorting_dropdown.price_descending' | t }}</option>
<option value="title-ascending" {% if sort_by == "title-ascending" %}selected{% endif %}>{{ 'collections.sorting_dropdown.title_ascending' | t }}</option>
<option value="title-descending" {% if sort_by == "title-descending" %}selected{% endif %}>{{ 'collections.sorting_dropdown.title_descending' | t }}</option>
<option value="created-ascending" {% if sort_by == "created-ascending" %}selected{% endif %}>{{ 'collections.sorting_dropdown.created_ascending' | t }}</option>
<option value="created-descending" {% if sort_by == "created-descending" %}selected{% endif %}>{{ 'collections.sorting_dropdown.created_descending' | t }}</option>
</select>
</div>
{% endif %}
</div>
Here are the important things worth mentioning:
The onChange="window.location.href=this.value" is a bit of JavaScript necessary to grab the value from the vendor dropdown and to update the web address (URL).
The for product_vendor in shop.vendors is a bit of Liquid necessary to grab all vendors and provide them one at a time to the dropdown.
The if collection.current_vendor contains product_vendor is also a bit of Liquid necessary when the vendor filter is in use. It checks for an active vendor filter and selects it in the dropdown after the page has reloaded.
The {{ product_vendor | url_for_vendor }} provides the URL used by the JavaScript in #1 above.
The {{ product_vendor }} provides the actual vendor name to the list.
The and collection.current_vendor == blank tells the page to hide the Tag and Sort dropdowns if a vendor filter was selected.
Here are the Shopify Docs which really helped me. This assumes you already understand the for loop and if statements which are a basic component of programming.
Understanding shop.vendors
Understanding collection.current_vendor
Understanding url_for_vendor
Understanding product_vendor
Understanding blank
Shopify doesn't allow for filtration by vendor at the moment (while keeping the collection relation to the vendor).
This was mentioned in a recent live Q&A with Shopify and it was confirmed that they are testing this. More info can be seen here: https://youtu.be/MDqDIIyxIcU?t=2078
You have to stick with the tags for now.

Assign the inner loop result into a variable

I have a loop like this in my django template and this having an inner loop
{% for productinfo in product_list %}
<tr>
<td>{{productinfo.attr}}</td>
<td>
<select class="form-control seller-combo" name="category">
<option value="">Select Attributes</option>
{% for attr in product_list %}
<option value="{{attr|mongo_id}}">{{ attr.attr }}</option>
{% endfor %}
</select>
</td>
</tr>
{% endfor %}
My problem is that each time when the outer loop is running the inner loop also run many times. I want to remove the inner loop from this and want to call this inner loop before the outer loop is running.
Like example the code should be like this,
{% for attr in product_list %}
<option value="{{attr|mongo_id}}">{{ attr.attr }}</option>
{% endfor %}
And assign the result of this code into a variable say it as result
Then attach this result like this,
{% for productinfo in product_list %}
<tr>
<td>{{productinfo.attr}}</td>
<td>
<select class="form-control seller-combo" name="category">
<option value="">Select Attributes</option>
{{result}}
</select>
</td>
</tr>
{% endfor %}
Doing like this i can increase my code performance
{% for attr in product_list %}
<option value="{{attr|mongo_id}}">{{ attr.attr }}</option>
{% endfor %}
make this as a seperate template this.html and {% include 'this.html' %}
OR
to increase the performance use with tag
{% with product_list as p_list %}
"write your for loop"
{% endwith %}