I have queries like following that I would like to implement it in front end:
MembershipPayment.objects.filter(group__name=tg.group_name).are_valid().count()
MembershipPayment.objects.filter(group__name=tg.group_name).Not_valid().count()
I know that I can pass this from view to front-end HTML, but the problem is that in the front end I have a query-set containing many "group"s. so I need to run a similar query for each of those "group"s.
I need something along these lines [this code of course won't work] in front:
{% for rec in groups %}
<tr>
<td>{{ MembershipPayment.objects.filter(group__name=tg.group_name).are_valid.count }}</td>
<td>{{ MembershipPayment.objects.filter(group__name=tg.group_name).not_valid.count }}</td>
</tr>
{% endfor %}
So I was wondering how can I achieve this without changing my model structure (if possible).
Why don't you do that logic in your view, by building a dict for each of your group, like:
def your_view(request):
...
groups: dict = dict()
for group_name in group_names:
groups[group_name]: int = MembershipPayment.objects.filter(group__name=group_name).are_valid().count()
return render(request,'your_template.html', {'groups': groups})
..and then pass it to your template, like:
{% for key, value in groups.items %}
<tr>
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
{% endfor %}
...key being the group name, value being the group count.
I ended up passing a dictionary like this in view:
groups_statistics={group1:{monthly_balance:250,weekly_balance:3000},group2:{monthly_balance:250,weekly_balance:3000}}
and then looping through its value as:
{% for rec,stat_dic in groups_statistics.items %}
<tr>
<td>{{ stat_dic.weekly_balance| get_value_from_dict:rec }}</td>
<td>{{ stat_dic.monthly_balance| get_value_from_dict:rec }}</td>
</tr>
{% endfor %}
here get_value_from_dict is a customized tag defined in dictionarytags.py as:
from django import template
register = template.Library()
#register.filter('get_value_from_dict')
def get_value_from_dict(dict_data, key):
"""
usage example {{ your_dict|get_value_from_dict:your_key }}
"""
if key:
return dict_data.get(key)
in the following folder:
my app>"templatetag" folder.
this folder contains:
__ init __.py
and
dictionarytags.py
and then in html I have this line in upper part:
{% load dictionarytags %}
Related
I have a problem. Consider an HTML table and it has rows and columns. I want to add a new row or column when I want it and I want it to be a record in the database. And I want to do this with django. What should I do?
I think I need to use django_table2 but I don't know how. I would be glad if you write a code sample. Thank you)
Say you have a model, you could get a list of objects like so;
def my_view(request):
context = {'object_list':MyModel.objects.all()}
return render(request, 'mypage.html', context)
Then in the template, you could do a few things to create tables:
Either, fully generate the table with Django, like so:
{% for object in object_list %}
<tr>
<td>{{object.data}}</td>
<td>{{object.data}}</td>
<td>{{object.data}}</td>
</tr>
{% endfor %}
This would create a new row for every object.
Another solution is:
{% for object in object_list %}
//Create row for every object
<tr>
{% for data in object.get_field_data %}
// Create column for every field in object
<td>{{data}}</td>
{% endfor %}
</tr>
{% endfor %}
Where get_field_data would be defined as a method on the model like so:
def get_field_data(self):
datalist = []
for field in self._meta.get_fields():
datalist.append(getattr(self, field.name))
return datalist
You could then even implement some checks on the get_field_data, for example, you could exclude fields.
def get_field_data(self):
datalist = []
for field in self._meta.get_fields():
if field.name != 'id':
datalist.append(getattr(self, field.name))
return datalist
You don't need to use any external package, you can do this easily by using the Django Template Language
Here is a code example using a ListView
# views.py
from django.views.generic import ListView
class ItemListView(ListView):
template_name = 'mytable.html'
model = MyModel
context_object_name = 'item_list'
<!-- mytable.html -->
...
<table>
<thead>
<tr>
<th>Name</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
{% for item in item_list %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.amount }}</td>
</tr>
{% endfor %}
</tbody>
</table>
...
In this way your template will have access to a list of objects called item_list which corresponds exactly to the records in the database table. You can cycle that list/queryset using a for loop that will automatically wrap that content in the html needed to make it part of the table.
So I have the following table in my template:
<tbody>
{% for user in users %}
<tr>
<td>{{ user.title }} </td>
{% for fruit in fruits %}
{{ sum|add:user|get_attr:fruit }}
<td>{{ user|get_attr:fruit }} </td>
{% endfor %}
{% for vegetable in vegetables %}
{{ sum|add:user|get_attr:vegetable }}
<td>{{ user|get_attr:vegetable }} </td>
{% endfor %}
<td>{{ sum }}</td>
{% endfor %}
</tbody>
"fruits" and "vegetables" are lists passed as context from the view. The following custom filter allows me to iterate through those lists extract integer values from the model "user". The table columns are generated the same way, so this filter has to be in the table:
#register.filter
def get_attr(obj, attr):
return getattr(obj, attr)
The variable "sum" is passed as context from the view with the value 0. I'm trying to make it summarize all the relevant row variables in the template, but it remains 0. As far as I can see there are three ways I could go about this:
Solve this in the template (as I'm trying now)
Generate the value in the view (although I have no idea how I would go about this)
Add some JS to solve it (would prefer to avoid this).
How should I go about solving this?
Solved this on the back end by generating a dictionary:
views.py
sum = {}
for user in users:
identity = user.pk
score = 0
all_food = fruits + vegetables
for food in all_food:
score += getattr(user,food)
sum[identity] = score
The summarized value can now be accessed in the template by using another custom template tag:
#register.filter
def get_value(dictionary, key):
return dictionary.get(key)
Adding it to the template:
{{ sum|get_value:user.pk }}
There is a module with 30 columns.
I query this table in the views.py to get the last record (last row).
To get the data in template (index.html), I have to write each column and in front of it, its value. I have to do it 30 times!
is there anything like {{form}} to get all the columns and their value automatically or at least by using {% for ... %}?
in views.py
def articlesindex(request):
data = Articles.objects.all().last()
return render(request, 'Articles\index.html', {'articles':data})
in index.html
{{ articles }} (does not work)
{{ articles.a_table }} (does not work)
{% for k,v in articles %} (does not work)
<tr>
<td>{{ k }}</td>
<td>{{ v }}</td>
</tr>
{% endfor %}
That is because last() return a single object in a queryset (see the documentation here). So, as it is a single object you will have a single row. You can render the object as follow:
<tr>
<td>{{ articles.attr_1 }}</td>
<td>{{ articles.attr_2 }}</td>
...
<td>{{ articles.attr_n }}</td>
</tr>
The attribute one by one
I'm trying to build a table in a template based on a variable number of fields.
The code I'm using is:
<table id="custom_report_table" class="display" width="100%">
<thead>
{% for field in fields %}
<th>{{ field }}</th>
{% endfor %}
</thead>
<tdody>
{% for CI in CIs %}
<tr>
<td>{{ CI }}</td>
</tr>
{% endfor %}
</tdody>
</table>
fields is a list with all the fields and CIs is a queryset with the data that needs to go into the table.
The problem is that I usually know the name of the fields so I can call each on individually when creating the cells in the usual way:
{{CI.field1}}
{{CI.field2}}
....
But now I can't hard code the fields' names as they are variable and come from the list.
Is there a way to do this?
Thanks,
Isaac
Just iterate again over CIs using items
{% for key,value in CIs.items %}
<td>{{ key }} {{value}}</td>
{%endof%}
If you only want to print items that are in fields:
{% for field_name, field_value in CIs.items %}
{% if field_name in fields %}
<th>{{ field_name }}</th>
<td>{{ field_value }}</td>
{% endif %}
{%endof%}
Solved by using .values in the queryset creation in the view.
And to reference the foreign keys for each field I had to build up the list of values with a list of field_name_foreign_field.
As the names for all foreign key fields followed a standard rule, it was quite easy with a for loop in the view.
In the template below, user.group is a number and it has to be shown as group_name.get(user.group) Are there any ability to pass to template group_name dict and use group_name.get(user.group) inside template?
<table>
{% for user in users %}
<tr>
<td>{{ user.name }}</td>
<td>{{ user.age }}</td>
<td>{{ user.group}}</td>
</tr>
{% endfor %}
</table>
In the spirit of django this logic should live in the code, not in the template. Can't you add a method user.get_group() that returns the group?
No, the dot notation doesn't allow for looking up names by variable value.
I would do this in the view, if it's specific to this one template.
for user in users:
users.group_name = group_name.get(user.group)
{% for user in users %}
{{ user.group_name }}
{% endfor %}
If it's applicable to all users, do as jammon suggested and define a method on User
Out of curiosity, can I see your models? Just curious why group is a number and where group_name comes from.