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

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>

Related

Jekyll - Create an index of lists ordered by tag

i would like to create an index of lists in jekyll of all tags and the corresponding posts.
My first approach, for-loops for every tag:
<h4>FRUITY</h4>
{% for post in site.tags.fruity %}
<ul class="posts">
<li>
{{ post.title }}
</li>
</ul>
{% endfor %}
<h4>SWEET</h4>
{% for post in site.tags.sweet %}
<ul class="posts">
<li>
{{ post.title }}
</li>
</ul>
{% endfor %}
...
This WORKS, but i have to manually create a new for-loop for every new tag.
My second approach, one loop to automatize this step so i dont have to worry about new or removed tags:
{% for tag in site.tags %}
<div class="medium-6 large-3 columns list-view-all">
<h4>{{ tag | first | upcase}}</h4>
{% for post in site.posts contains tag %}
<ul class="posts">
<li>
{{ post.title }}
</li>
</ul>
{% endfor %}
</div>
{% endfor %}
The first part works, every tag becomes a header.
in the inner for-loop ALL posts containing any tag get listed. So the lists for every tag are equal.
The Question:
How can i make a list for every tag with only the posts corresponding to the respective tag?
Thanks for your help!
{% for tag in site.tags %}
<div class="medium-6 large-3 columns list-view-all">
{% assign currentTag = tag | first %}
<h4>{{ currentTag | upcase}}</h4>
{% for post in site.posts %}
{% if post.tags contains currentTag %}
<ul class="posts">
<li>
{{ post.title }}
</li>
</ul>
{% endif %}
{% endfor %}
</div>
{% endfor %}

work around setting variables in django templates

I have this code that I used from twig to display sections according to the same date.
I'm trying to use the same code in Django but I can't set variables in its template system. What is the sane way to do this? The correct way? How do people tackle such a problem?
{% set date = "prout" %}
{% for article in articles %}
{% if article.date != date %}
{% if date != "prout" %}
</ul>
</section>
{% endif %}
{% set date = article.date %}
<section class="row">
<h2>{{ article.date }}</h2>
<ul>
<li>+ {{ article.titre }}</li>
{% else %}
<li>+ {{ article.titre }}</li>
{% endif %}
{% endfor %}
</ul>
</section>
The closer concept to 'set' variables is with tag. Quoting Built-in template tags and filters django docs:
with
Caches a complex variable under a simpler name. This is useful
when accessing an “expensive” method (e.g., one that hits the
database) multiple times.
For example:
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}

Cumulative count in recoursetree?

Using django-mppt I want to browse my category hierarchy displaying the ammount of objects related to the current category in any of it's children.
Much like drill_down_for_node in the example shown, but only with the current node childrens...
The optimal would be
{% recursetree obj.get_children cumulative count model.Foreignkey.category in o_count%}
<li>
<h2>{{ node }}</h2>
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }} ({{o_count}})
</ul>
{% endif %}
</li>
{% endrecursetree %}
Any pointers?
Found a function for this on the TreeManager:
https://github.com/django-mptt/django-mptt/blob/master/mptt/managers.py#L250
Add the counts to the queryset in your view:
context['qs_with_related_count'] = model1.objects.add_related_count(
obj.get_children(),
model2,
'category',
'o_count',
True
)
and in template:
{% recursetree qs_with_related_count %}
<li>
<h2>{{ node }} ({{ node.o_count }})</h2>
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
Unfortunately I was trying to use a ManyToManyField as rel_field:
https://github.com/django-mptt/django-mptt/issues/90
but it looks like you are in luck ('category' not 'categories') :)

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 regroup not working as expected

I have the following view in my django application
def ViewSale( request ):
salecur = Sale.objects.filter(user=2).order_by('sale_date')
return render_to_response('myapp/sale.html',{'salecur':salecur})
my template looks like this
{% regroup salecur by sale_date as sale_list %}
<ul>
{% for sale_date in sale_list %}
<li>{{ sale_date.grouper }}
<ul>
{% for sale in sale_list %}
<li>{{ sale.item }} - {{ sale.qty }} </li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
When i render the page i get the grouper sale_date.grouper printed, but {{ sale.item }} and {{ sale.qty }} in the inner loop shows nothing! Blank.
What am i missing?
Gath
{% regroup salecur by sale_date as sale_list %}
<ul>
{% for sale_date in sale_list %}
<li>{{ sale_date.grouper }}
<ul>
{% for sale in sale_date.list %}
<li>{{ sale.item }} - {{ sale.qty }} </li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
See the documentation on regroup:
{% regroup %} produces a list of group objects. Each group object has two attributes:
grouper -- the item that was grouped by (e.g., the string "Male" or "Female").
list -- a list of all items in this group (e.g., a list of all people with gender='Male').