SOLVED
Explanation here: Performing a getattr() style lookup in a django template
I am looking to build tables on our business website dynamically. At the moment we have multiple pages with tables and filters that allow for search but I have to go in and construct a table for each of them based on the data that should be displayed. I was hoping to find a way to use one main template file that can encompass most instances for creating a new page. The difficulty I am having is trying to loop through the data and place it in the correct cell.
(Some code has been removed for readability.)
View:
def newDynamicView(request):
jobs = Jobstable.objects.all().order_by('-index')
filter = NewFilter(data, queryset = jobs)
fields_model = filter._meta.fields
fields_text = []
for field in fields_model:
fields_text.append(FIELD_NAME_TEXT[field])
return render(request, 'MYSQLViewer/olivia.html', {'filter': filter, 'fields_model': fields_model, 'fields_display': fields_text})
Current Template (Relevant info):
<div class="table-responsive">
<table id="data_table" class="table table-dark table-bordered table-responsive">
<thead class="thead-light">
{% for field in fields_display %}
<th>{{field}}</th>
{% endfor %}
</thead>
<tbody>
{% for job in filter.qs %}
<tr>
{% for model_field in fields_model %}
<td class="pt-3-half edit {{model_field}}" contenteditable="true" id="{{model_field}}-{{job.index}}">{{job.model_field}}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
From what I understand, the problem (and possible solution?) lies in this tag:
{{job.model_field}}
My idea was to grab the job attribute using model_field but obviously, that doesn't work.
In its current state, all data is passed from view to template correctly.
Any help is greatly appreciated.
Related
I have a model that is referenced by a generic ListView, and feeds into a template. Attempts to create a table in the template give me a TypeError: not iterable - what am I doing wrong?
Sample code
Class bookmodel(models.Model):
Book = models.CharField(max_length=255)
Author = models.CharField(max_length=255)
Views
Class bookview(generic.ListView):
model = bookmodel
template = “books.html”
Which generates an object_list something like:
<Queryset [<bookmodel: Grapes of Wrath >, <bookmodel: I, Robot>]>
The template is laid out as follows:
{% extends ‘base.html’ %}
{% block content %}
<table>
<thead>
<tr>
<th> book </th>
<th> author </th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
{% for field in object %}
<td> {{ field }} </td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
But this fails with the aforementioned error.
The linked question kindly suggested by #Karioki in his comment proposed the following code:
def attrs(self):
for field in self._meta.fields:
yield field.name, getattr(self, field.name)
The yield function inexplicably didn't work for me in my template either from a view or a template tag:
The following derivative code did:
def get_values(self):
value_set = [getattr(self, field.name) for field in self._meta.fields]
return value_set
While this still feels clunky to me, I'm marking it as a straw man answer but am hopeful that there will be another answer that provides a more efficient way to investigate a database record in the template in Django.
In a Django application I have several html pages with a similar structure. I am already using a base_site.html template for all my project but for these other pages I would like to use a second template to create tables. These tables could have more or less rows and columns than others.
My idea was that the functions in views.py would send a list of the headers for any given page together with a dict of the data to populate the table, then in the html page I would iterate the list of headers to place the headers in the table then I would iterate the dict to populate the table with the data.
How can I have a table-template.html to use a variable say headers from every function in views.py whenever they are called?
Something like table-template.html
<h1>TEST</h1>
<table>
<tr bgcolor="#ccc">
<th>{% for h in headers %} {{ h }} {% endfor %}</th>
</tr>
</table>
Considering that every function in views.py would return its own headers list
Then how can I use it in any of the html pages
{% extends "admin/base_site.html" %}
{% load static %}
{% block content %}
{% include "table-template.html" %}
{% load static %}
{% for key,value in mydict.items %}
<table>
<tr>
<td>{{ value }}</td>
</tr>
</table>
{% endfor %}
The table-template.html could be use a slight change since you want each value in a tag
<h1>TEST</h1>
<table>
<tr bgcolor="#ccc">
{% for h in headers %}
<th> {{ h }} </th>
{% endfor %}
</tr>
</table>
This will create the correct table headers for you. You can send the headers list from your view render method in the context dictionary.
Feel free to comment if this doesn't give the complete answer you are looking for.
I actually managed to find a solution by creating a template that inherits my base_site.html and on all my other templates I will inherit my new_template.html. So it's kind of a grand parent template inheritance.
I just included all the variables I want in the template (which are all named equally across all functions in views.py) and when the template is extended in a new page it gets the values of the variables from the respective function in views.py.
I have two Django models that record time. Model one records time during the morning and Model two records time during the evening. I want to present both of these times along with the difference between the times within an HTML table but am confused about how to do it. I am new to Django and would really appreciate some advice.
This is what I have so far:
models.py:
class Alltime(models.Model):
id= models.ForeignKey(User, on_delete = models.CASCADE)
mtime = models.DateTimeField()
etime = models.DateTimeField()
views.py:
def panel(request):
time_data = User.objects.filter(pk__gt=1) #I need all data except for the default Super User account
get_time = Alltime.objects.all()
return render(request, 'users/interface.html', {'data': time_data, "get_time": get_time})
panel.html:
<form>
{% csrf_token %}
<table>
<tr>
<th>Name</th>
<th>Morning timeE</th>
<th>Evening time</th>
<th>Difference in hours</th>
</tr>
{% for data in data %}
<tr>
<td>{{data.username}}</td>
{% endfor %}
{% if get_time %}
{% for m in get_time %}
<td>{{m.mtime}}</td>
<td>{{m.etime}}</td>
{% endfor %}
{% else %}
<td> Not available </td>
{% endif %}
</tr>
</table>
</form>
How can I get the difference between the times and place them within the HTML table?
If I understand correctly what you want to do, then you can/need to structure your data differently. An easy way is to prepare the data in your view:
def panel(request):
time_data = User.objects.filter(pk__gt=1)
time_table=[]
for user in time_data:
morning_time = Morning.objects.filter(user=user)
evening_time = Evening.objects.filter(user=user)
diff = morning_time - evening_time
time_table.append((user.name, morning_time, evening_time, diff))
return render(request, 'users/interface.html', {'data': time_table})
And in the template:
<table>
<tr>
<th>Name</th>
<th>Morning timeE</th>
<th>Evening time</th>
<th>Difference in hours</th>
</tr>
{% for line in data %}
<tr>
<td>{{line.0}}</td>
<td>{{line.1}}</td>
<td>{{line.2}}</td>
<td>{{line.3}}</td>
</tr>
{% endfor %}
</table>
You need to add the handling of not existing data in the view code.
Some remarks:
The whole thing does not really make sense to me. I guess you will need to filter for dates too. But you should get the idea from this. And why is it in a form?
You can add a property to the Alltime model that returns the difference between the morning and evening time
#property
def diff(self):
return self.etime - self.mtime
Then in your template you can use this property
{% for m in get_time %}
<td>{{m.mtime}}</td>
<td>{{m.etime}}</td>
<td>{{m.diff}}</td>
{% endfor %}
I am trying to split a list from my model across two columns, using this html code in the template:
< div class ="col-md-6" >
{%for value in object_list %}
<ul>< ahref="/sites/{{value.url}}/">{{value.Site}}</a></ul>
{% endfor %}
I was planning to achieve this with the slice tag to filter the list, e.g.:
{%for value in object_list|slice:"10:20" %}
It does not work however, and I think it might be because I have context data i.e. {{value.Site}}, instead of just {{Site}} for example. This is the corresponding view:
class homeview(ListView):
template_name = 'annual_means/home.html'
def get_queryset(self):
return AnnualMean.objects.values("Site", "url").distinct()
What do I need to do to get the slice to work?
I think, what you need is this:
<table>
<tr>
<th>URL</th>
<th>SITE</th>
</tr>
{% for value in object_list %}
<tr>
<td>{{value.url}}</td>
<td>{{value.Site}}</td>
</tr>
{% endfor %}
</table>
URLs and Sites will be displayed as a table.
I've got a problem displaying items in a table, that is both regrouped by columns and rows.
I wrote an app, where employees can log a workday and set a status (office, vacation etc.)
I pass all day items to the template by:
results = Tage.objects.filter(*args, **kwargs)
In the template I regroup the columns by
{% regroup results|dictsort:"employee.id" by employee as employee_entries %}
and loop through them
<tr>
<th>Date</th>
{% for ma in employee_entries %}
<th>{{ ma.grouper }}</th>
{% endfor %}
</tr>
Thats works fine.
Next thing is regrouping the rows by the day.
{% regroup results|dictsort:"employee.id"|dictsortreversed:"starttime" by starttime|date:"d. E Y" as day_entries %}
{% for te in day_entries %}
<tr>
<th colspan="5" style="border-right: 0px;">{{ te.grouper }}</th>
</tr>
That also works fine.
Now the tricky part:
I want to display the status of the day an employee has logged by:
<tr>
<th>Status</th>
{% for result in te.list %}
<th>{{ result.status }}</th>
{% empty %}
<th></th>
{% endfor %}
</tr>
That works fine, if all employees have logged that specific day. If someone hasn't logged a day like others, all status columns are in the wrong place. Of course, that happens because te.list is not the same length as the employee list.
Has anyone an approach to such a problem? I googled around a lot, but didn't find a straight-forward solution to such a problem.
Thanks in advance
Conrad
I decided to render the table header and body inside the view and pass it to the template and render it with
{{ theader|safe }}
and so on.
The problem was too complex for the capabilities of Django's template system.