Django: Cannot reference a fieldname in template which contains a dot - django

The object which I pass from view to template has a few fields which are dynamically incremented and allocated
e.g the object looks like:
row = {
'id':id,
'input.object1':obj1
'input.object2':obj2
}
I am trying to access the value of "input.object1" as "{{ row.input.object1 }}" in template.
but the page does not show anything for this field (same problem for "input.object2". But "row.id" works fine)
{% for row in row_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.input.object1 }}</td>
<td>{{ row.input.object2 }}</td>
</tr>
{% endfor %}
Is there anyway to access these values in html ?
Thanks in advance :)

You can try the following structure of your context:
row = {
'id': id,
'input': {'object1': obj1, 'object2': obj2}
}
which will allow you to access the values the way you try it in your template. But if that structure is dynamic and variable in length, you are better off using a list:
row = {
'id': id,
'input': [obj for obj in ....]
}
and in the template
{% for row in row_list %}
<tr>
<td>{{ row.id }}</td>
{% for obj in row.input %}
<td>{{ obj }}</td>
{% endfor %}
</tr>
{% endfor %}

Django's template languages uses dots in variables names to indicate an index (lists etc), key (dict-likes) or attribute (anything else) lookup, so for {{ row.input.object1 }} it first tries to resolve row.input as either row["input"] or row.input - none of which exists.
You want to make input either a list or dict, ie:
row = {
'id':id,
'input'= [obj1, obj2]
}
and then
{{ row.input.0 }} - {{ row.input.1 }}
or
row = {
'id':id,
'input'= {"object1": obj1, "object2": obj2}
}
and then
{{ row.input.object1 }} - {{ row.input.object2 }}

Related

Summarizing values for each row in a table dynamically generated from django context variables

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 }}

Django database filter in front end

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 %}

Django - How to retrieve columns in template automatically from a query in views.py?

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

Run python in a html template while iterating though a list

def ViewCharges(request):
account = get_object_or_404(StripeAccount, team_members=request.user)
payment_requests = PaymentRequest.objects.filter(company=account).order_by('-created')
return render(request, 'dashboard/charges.html',{'payment_requests':payment_requests})
This is how my template looks after doing
{% for request in payment_requests %}
<tr>
<td>{{ request.name }}</td>
<td>{{ request.email }}</td>
<td>{{ request.amount }}</td>
<td>{{ request.paid }}</td>
<td><a href="/dashboard/charges/{{ request.pk }}" class='btn btn-dark btn-sm'>Manage</a></td>
</tr>
{% endfor %}
And in my models, I store the paid field in pence (e.g 100 = £1), this is for stripe. And I can properly format it by doing
real_amount = "{:.2f}".format(amount / 100)
this works fine until I need to do it in a for loop in html, is there a way I can do this in the html doc
<tr>
<td>Bob</td>
<td>Bob#example.com</td>
<td>£20</td>
<td>Yes</td>
<td><a href="/dashboard/charges/3523" class='btn btn-dark btn-sm'>Manage</a></td>
</tr>
The rest is fine I just need some help with that formatting, does anybody have any suggestions?
Create a property on your models to calculate real_amount. Then you can access this property in your HTML template or anywhere else just like any other field attribute of your model.
Example:
class MyModel(...):
...
#property
def real_amount(self):
return "{:.2f}".format(self.amount / 100)
Then in your templates:
{{ request.real_amount }}

Outer loop value does not matches with inner loop value: Django template

I have written a nested loop and doing value comparison between data coming from outer loop with inner loop. Below is my template code :-
<tbody>
{% for col in filter2.qs %}
<tr>
{% for mso in filter1.qs %}
{{ col.box_id }} vs {{ mso.box_id }}
<br>
{% if mso.box_id == forloop.parentloop.col.box_id %}
<td>{{ mso.mso_id }}</td>
<td>{{ col.box_id }}</td>
<td>{{ col.channel_id }}</td>
{% endif %}
{% endfor %}
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
</tbody>
Problems are :
When i do print {{ col.box_id }} vs {{ mso.box_id }} i can see values
When i do print {{ col.box_id|length }} vs {{ mso.box_id|length }} i see length of outer loop value as 0.
If condition below the prints never runs hence no data is inserted in the table.
I am getting data for both the loops from views.py
def search(request):
user_list1 = VCB_Execution_Details.objects.all()
user_filter1 = ReportFilter_VCB_Execution_Details(request.GET, queryset=user_list1)
user_list2 = VCB_Details.objects.all()
user_filter2 = ReportFilter_VCB_Details(request.GET, queryset=user_list2)
print(user_filter2.qs)
print(type(user_filter1))
return render(request, 'user_list.html', {'filter1':user_filter2,'filter2': user_filter1})
filters.py
class ReportFilter_VCB_Execution_Details(django_filters.FilterSet):
class Meta:
model = VCB_Execution_Details
fields = ['box_id','channel_id']
class ReportFilter_VCB_Details(django_filters.FilterSet):
class Meta:
model = VCB_Details
fields = ['box_id','mso_id']
So Finally i got the answer, problem was the object type was VCB_Execution_Details vs str. I tried checking the data type in def search(request): by printing variable type for each data in queryset of user_list1 and user_list2