Django Templates: Group Items in Threes

Django templates: Group items in Threes

Whenever you find yourself trying out complex code inside templates, its usually a good indication that it should be moved elsewhere. One of the alternative solutions have already been suggested, which is to move the code into your view function.

The other solution would be to expose the functionality via a new template tag. One of the reasons you would choose this solution over the view solution, is that you'll be able to easily re-use the code for pages that are served with different views.

class GroupPaintingsNode(template.Node):
def __init__(self, num, varname):
self.num, self.varname = int(num), varname

def render(self, context):
paintings = Painting.objects.all # do your fetching/filtering here..
l = [[] for i in range(len(paintings))]
i = 0
while i < len(paintings):
l[i].append([p.title for p in paintings[i:i+self.num]])
l[i].append([p.desc for p in paintings[i:i+self.num]])
i += self.num
context[self.varname] = l
return ''

def group_paintings(parser, token):
tokens = token.contents.split()
if len(tokens) != 4:
raise template.TemplateSyntaxError, "'%s' tag requires three arguments" % tokens[0]
if tokens[2] != 'as':
raise template.TemplateSyntaxError, "Second argument to '%s' tag must be 'as'" % tokens[0]
return GroupPaintingsNode(tokens[1], tokens[3])
group_paintings = register.tag(group_paintings)

In template code you would use it like this:

{% group_paintings 3 as paintings %}
{% for p in paintings %}
{% for title in p.0 %} {{ title }} {% endfor %}<br>
{% for desc in p.1 %} {{ desc }} {% endfor %}
{% endfor %}

Use Django view to group every 3 objects into seperate context variables?

You can "unpack" the elements in separate variables:

def project_index(request):
projects = Project.objects.all()
project_len = len(projects)
# for nine elements
group1, group2, group3 = zip(*[iter(projects)]*3)
context = {
'projects': projects,
'group1': group1,
'group2': group2,
'group3': group3
}
return render(request, 'project_index.html', context)

or with an arbitrary number of elements:

def project_index(request):
projects = Project.objects.all()
project_len = len(projects)
groups = zip(*[iter(projects)]*3)
context = {
'projects': projects,
**{f'group{i}': val for i, val in enumerate(groups, 1)}
}
return render(request, 'project_index.html', context)

That being said, passing these as individual elements, might not be a good idea. Since at the template end, you then will somehow have to access it. Therefore it might be better to pass it as an iterable of iterables, and thus use two nested loops in the template.

Django: Can't GROUP BY on a template table

I'm not entirely sure what you're trying to do. It's either to total up each date or to sum all totals. I've provided ways to do both.

from django.db.models import F, Sum, Count

resultado = Asiento.objects.filter(
Empresa=request.session['codEmp'],
codcta=cod_cta
).exclude(anulado='S').order_by(date).values('date').annotate(
dcount=Count('date'),
add_sum=Sum('add'),
sub_sum=Sum('sub'),
).annotate(
total=F('add_sum')+F('sub_sum')
)

This will give you each date with fields representing add_sum, sub_sum, and total. If you wanted to aggregate all the totals of all dates then you'd want to do then:

print(resultado.aggregate(total_all=Sum('total'))['total_all'])

Django and HTML template : Group by panels with common object attributes

You should restructure your data in the view so that it's already prepared for the template. Django's template system is built in a way to avoid this type of logic.

You might be able to do it simply like this:

from collections import defaultdict

research_categories = defaultdict(list)
for element in test_research:
research_categories[element.publication.category].append(element)

Then use research_categories in your template.

Using multiple model fields to regroup list in Django template

Your model function is correct but it should contain a % before the braces:

def display_name(self):
return "%s, %s" %(self.name, self.city)

Your view should pass a list of objects and not values.

Let the list be tp, so your template code should be something like this:

{% regroup tp by display_name as tp_list %}

<ul>
{% for t in tp_list %}
<li>{{ t.grouper }}
<ul>
{% for item in t.list %}
<...something of your code....>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>

This should work out for you well enough.

Django read 3 variables at once from list

Django templates let you check 'where you are' in the for loop, so all you have to do is open and close your rows appropriately:

{% for user in user_list %}
{% if forloop.counter0|divisibleby:"3" %}<div class="row">{% endif %}
<div class="col align-self-center">
<form> <button class="btn btn-outline-primary btn-sm btn-block" formaction="{% url 'interface:data' user.id %}">{{user.id}}</button> </form>
{% if forloop.last or forloop.counter|divisibleby:"3" %}</div>{% endif %}
{% endfor %}


Related Topics



Leave a reply



Submit