How do I make nested regroups in Django? - django

I've got the following situation in this system:
Each category of products has many subcategories, and each subcategory has many products under it.
I'm trying to make a product searh, which returns a list, and in my template, I show an overview of the results, like this:
Cellphones
Dumbphones (2 results)
Smartphones (3 results)
Monitors
CRT (1 result)
LCD (3 results)
I'm my template I have only the list of products. I've tryed many combinations of nested regroups, without success. Any ideas?

You can try something like this:
<div>
...
{% regroup results|dictsort:"subcategory.category" by subcategory.category as categories %}
<ul>
{% for category in categories %}
<li>{{ category.grouper }}
{% regroup category.list|dictsort:"subcategory" by subcategory as subcategories %}
<ul>
{% for subcategory in subcategories %}
<li>{{ subcategory.grouper }}
<!--The same way you can render a subcategory.list which is the prosucts list-->
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
acceptance_report.company as companies %}
...
</div>

Related

Display column names in Django template without knowing them ahead of time

I have a queryset that I am passing to Django. There are 100 columns or so. I want to render this single object as either an HTML list without knowing all the column names. I know I could use ListView, but I want more control to do something like this within a TemplateView (with additional graphs):
<ul>
{% for obj in queryset %}
<li>
{% for column in obj %}
[Name of Column]: {{ column }}
{% endfor %}
</li>
{% endfor %}
</ul>
So I want to render both the name of the column and the column data without knowing the name of the column beforehand. Ordinary I'd do this:
<ul>
{% for obj in queryset %}
<li>
Column 1: {{ obj.column1 }}
Column 2: {{ obj.column2 }}
...
Column 100: {{ obj.column100 }}
</li>
{% endfor %}
</ul>
But this is a bit tedious and requires writing out each column name by hand.
Could you try this
<ul>
{% for obj in queryset %}
<li>
{% for column in obj.column_set.all %}
[Name of Column]: {{ column }}
{% endfor %}
</li>
{% endfor %}
</ul>

BigCartel : {{ category.name }} and {{ artist.name }} display per item on Products page

I'm editing a theme in BigCartel and would like to display both the category name and the artists name underneath each product on the general 'Products' page of my BigCartel store. I have the 'Artists' category turned on (and have assigned each product to a category and an artist) and have used the code below but the names are still not displaying...They only show up when I search the store by category or Artist. (I've included 'Category' and 'X Artists Name' for styling only and will remove them once the issue is resolved.)
Any help on this would be greatly appreciated!
[Updated 03.12.2015]
The code below works fine when viewing a specified individual category or artist, however I would like to display both the Category and Artist name on the general Products page.
<span class="meta-category-name">Category {{ category.name }}</span>
{% if artists.active != blank %}
<span class="meta-artist-name">X Artists Name {{ artist.name }}</span>
{% endif %}
Ok I worked it out - For anyone elses benefit the code below solved it.
{% for category in product.categories %}
<span class="meta-category-name">{{ category.name }}</span>
{% endfor %}
{% for artist in product.artists %}
{% if artists.active != blank %}
<span class="meta-artist-name">{{ artist.name }}</span>
{% endif %}
{% endfor %}
</div>

Django and how to check if object has children

as a very much of a newbie in Django/python world I fail to find a way to check whether an object has children.
An example:
Class MyItems
title = models.CharField(max_length=50)
parent = models.ForeignKey('self',null=True, blank=True,related_name='subitems')
Then in my template:
{% for item in MyItems %}
<li> {{ item.title }} </li>
{% if item **IS A PARENT OF CHILDREN** %}
<p>This is what I want</p>
{% endif %}
{% endfor %}
I can see if an item has a parent no problem, but how to do it other way around, tell if an item is a parent to other item?
Thanks!
if you want a recursive parent child relationship between your objects you should look at using MPTT
http://django-mptt.github.com/django-mptt/
<ul class="root">
{% recursetree nodes %}
<li>
{{ node.name }}
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
talked about in the cookbook here:
https://code.djangoproject.com/wiki/ModifiedPreorderTreeTraversal
to understand how MPTT works at a data level, have a look at http://en.wikipedia.org/wiki/Nested_set_model
The problem with the obvious solution, is that for each additional level children, another query is required - which gets extremely inefficient.
# this is an additional query AND will not be recursive.
{% if item.child_set.all.count > 0 %}
If I understood the question correctly, it should be as simple as this:
{% if item.subitems.exists %}

Django template and splitting the variable list

In my django view, I pass a list that contains several items.
My html design is like this:
<ul>
<li>
<div>1st item</div>
<div>2nd item</div>
</li>
<li>
<div>3th item</div>
<div>4th item</div>
</li>
<li>
<div>5th item</div>
<div>6th item</div>
</li>
</ul>
You see the pattern, every two items, I need to split them and put into a new <li></li>. How can I loop and divide these variables by every two using {% for item in my_list %}?
You could try something like this which isn't particularly elegant and isn't tested in any way!
{% if list_of_items %}
<ul>
<li>
{% for item in list_of_items %}
<div>{{ item }}</div>
{% cycle '' '</li><li>' %}
{% endfor %}
</li>
</ul>
{% endif %}
You could re-arrange the list in your view first to make it a list of lists, or alternatively you could write your own batch filter.
As far as I know there isn't a really easy django template way of doing what you want - Django templates are deliberately restrictive to encourage you to write python code instead.
If the items have some property that groups them naturally into pairs, you can use regroup:
{% if list_of_items %}
<ul>
{% regroup list_of_items by property as item_chunks %}
{% for chunk in item_chunks %}
<li>
{% for item in chunk.list %}
{{ item }}
{% endfor %}
</li>
{% endfor %}
</ul>
{% endif %}
It's a couple more lines than Nick's solution, but if those elements do have a property that joins them naturally, I would say that this is a more elegant solution.
you might want to enumerate your total list of 6 elements in batches of size 2 which gives you 3 batches and then loop through each batch.
To do this, you can add a custom batch filter in your templatetags directory. Here is the documentation for adding custom tag/filter.
https://docs.djangoproject.com/en/1.9/howto/custom-template-tags/
Your custom filter can be something like this.
#register.filter
def batch(iterable, n=1):
l = len(iterable)
for ndx in range(0, l, n):
yield iterable[ndx:min(ndx + n, l)]
In your html
{% for batch in yourlist|batch:2%}
<li>
{% for element in batch %}
<div>{{element}}</div>
{% endfor %}
</li>
{% endfor %}
Updating this answer for Django 3.1
{% block content %}
<div class="row">
{% for product in products %}
<div class="col-md-auto">
<h5>{{ product.name }}</h5>
</div>
{% if forloop.counter|divisibleby:"6" %}
</div>
<div class="row">
{% endif %}
{% endfor %}
</div>
{% endblock content %}

Django template question?

I need to display all the videos within a certain playlist. I can display all the avaliable playlists by using this loop:
{% for p in playlists %}
{{ p.playlist.name }}
{% endfor %}
How can I display all the videos in each playlist too?
It's hard to say since you don't show your models, but something like this could work:
<ul>
{% for p in playlists %}
<li>{{ p.playlist.name }}
<ul>
{% for v in p.playlist.videos %}
<li>{{ v.name }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
I'm assuming your videos have a ForeignKey(Playlist, related_name="videos") field.