Django showing values of an annotated queryset without knowing the filed name - django

I´m building a dashboard where you can cross data from a sales database.
For example, sales by seller, products by client, etc. I let the user choose both option 1 and option 2.
I get the form back to the view and annotate the model with those options:
if filter_opts.is_valid():
option_1 = filter_opts.cleaned_data["option_1"]
option_2 = filter_opts.cleaned_data["option_2"]
results = ventas.values(option_2).annotate(Count(option_1, distinct=True))
The annotation works fine and if I just print the queryset in the template
{% for case in results %}
{{ case }}
{% endfor %}
I can see it like:
{'cliente': '502 EMSUR', 'prod_nombre__count': 9}
Then in the template I want to show only the values. But I can´t tell forehand which would be the value name to do something like this:
{% for case in results %}
{{ case.option_1 }}
{{ case.option_2 }}
{% endfor %}
If I iterate over the result I can see the field name:
{% for case in results %}
{% for item in case %}
{{ item }}
{% endfor %}
{% endfor %}
How can I show the values of that fields?
Thanks!

Since each case in results is a dictionary, you can use the property .items inside the template to iterate through its keys and values:
{% for case in results %}
{% for item, value in case.items %}
{{ item }} - {{ value }}
{% endfor %}
{% endfor %}

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>

Django forms how to dynamically render fields in a loop

Let's say I have a form with some fields. Some of those fields are units of measurements:
['quantity_units', 'weight_units', 'dimension_units']
I also have these fields:
['quantity', 'weight', 'dimension']
I would like to display the unit of measurement right beside the field:
Quantity: ___________________ _______<unit of measurement drop-down list>______
I thought I should first loop through the form's fields. For each iteration through the form's fields, I would check if the field name is in the units_list, if it is, then I would render the field and its unit field like so:
{% for field in form %}
{% for field_name in units_fields %}
{% if field.name in field_name %}
{{ field|add_class:"site-form-control" }} {{ form.field_name}}
{% else %}
{% ifchanged %}
{{ field|add_class:"site-form-control" }}
{% endifchanged %}
{% endif %}
{% endfor %}
{% endfor %}
This does not render the unit of measurement field with the drop-down list widget.
Any ideas how to fix this?
Edit:
I noticed that for some reason, Django displayed the {{ field }} twice and did not display {{ form.field_name }}. To manually choose the field, I wrote a template filter to get the value given the key for a dictionary. Then, I used it on the {{ form.fields }} which is an orderedDict
{% for field_name in units_fields %}
{% if field.name in field_name %}
{{ form.fields|dict_key:field_name }}
{% else %}
{% ifchanged %}
{{ field|add_class:"site-form-control" }}
{% endifchanged %}
{% endif %}
{% endfor %}
This renders the text representation of the field I want:
<django.forms.fields.ChoiceField object at 0x000001E5F35F3C18>
Any help to convert this text to an actual field is appreciated
The way I solved this was to write a simple tag that returns a boundfield object <django.forms.boundfield.BoundField object at 0x0000025 instead of <django.forms.fields.ChoiceField object at 0x000001E5F35F3C18>
#register.simple_tag(takes_context=True)
def get_form_field(context, form, field_name):
''' Given a form and a field_name, it returns form.field'''
try:
field = form[field_name]
except KeyError:
field = None
return field

Iterate through Django queryset within template

I have created a custom filter that returns a queryset of objects.
in: templatetags
#register.filter(name = 'create_html_for_deleting_notes')
def create_html_for_deleting_notes(task_pk):
corresponding_notes = Note.objects.filter(its_task = Task.objects.filter(pk = task_pk))
return(corresponding_notes)
in template:
{% for corresponding_task in corresponding_tasks %}
<h5>{{ corresponding_task | create_html_for_deleting_notes }}<h5/>
{% endfor %}
This works in printing out my queryset. I would like to iterate through that queryset, something like:
in template:
{% for corresponding_task in corresponding_tasks %}
{% for note in corresponding_task | create_html_for_deleting_notes %}
{{ note }}
{% endfor %}
{% endfor %}
But this gives me the error 'for statements should use the format "for x in y"'
Thank you for the help!
You need to remove the spaces around the filter | character.
However, I don't think you need the filter at all. You didn't post your model, but it seems like you have a foreignkey relationship between Task and Note, so you should just use the reverse accessor:
{% for corresponding_task in corresponding_tasks %}
{% for note in corresponding_task.note_set.all %}
{{ note }}
{% endfor %}
{% endfor %}

Variable which is a database query doesnt render properly in template

My template doesnt render the key , values for the variable table which is a dictionary.
{% for key, value in table.items %}
<p> {{key}} : {{value}}</p>
{% endfor %}
The was how the variable 'table' was derived. Client is a model and Client_FirstName is the attribute of the model.
table = Client.objects.filter(Client_FirstName__startswith='p').values()
I am just trying to do a database query which i just learn from here
There may not be any data in the database. Try this.
{% if table|length %}
{% for key, value in table.items %}
<p> {{ key }} : {{ value }}</p>
{% endfor %}
{% else %}
<div>There are no data in the database</div>
{% endif %}
I was rendering the database values wrongly on the template , this is how it should be done for a list of dictionary
{% for x in table %}
{% for key,values in x.items %}
<p> {{key}} : {{values}} </p>
{% endfor %}
{% endfor %}

Dictionary with arrays in django templates

I have dictionary with arrays inside:
dicarr = {'category': ['post1','post2', 'e.g.'], 'category2': ['post1','post2']}
Array is filled in one cycle:
dicarr = {}
for category in Categories.objects.all():
category_posts = Post.objects.filter(category=category)
dicarr[category] = [post for post in category_posts ]
How can i get access to array from django template? I tried:
{% for arrdic in dicarr %}
{{ arrdic.name }}
{% for i in arrdic.posts %}
{{ i.name }}
{% endfor %}
{% endfor %}
But isn't working.
Assuming you have a foreign key pointing to Category on your Post, you don't even need to do it this complicated. All you need to is pass this to the template:
categories = Category.objects.all()
Then you can iterate like this in the template:
{% for category in categories %}
{{ category.name }}
{% for post in categories.post_set.all %}
{{ post.name }}
{% endfor %}
{% endfor %}
You can do this with any foreign key relationships. Hope that answers your question!
Following your original code, your template should be (also see for tag docs):
{% for category, posts in dicarr.items %}
{{ category.name }}
{% for post in posts %}
{{ post.name }}
{% endfor %}
{% endfor %}
But this isn't the best way to do this, because your view will produce number of queries equal to the number of categories. See my answer to a similar question for a more efficient solutions.