Issue
I want to display a simple query in my database as an HTML table. But I am missing something either in the template or general logic of data management in Django.
First I am creating a model like that:
class Book(models.Model):
title = models.CharField(max_length=128, unique =True)
quantity = models.IntegerField(default=1)
Then making a view with a context containing both the column's names of the query and the query object such as :
def books(request):
context = {"rows":Book.objects.all(),"fields" : Book._meta.get_fields()}
return render(request,"blog/books.html",context)
Finally I am trying to iterate over the value of the query in my template so I can put them in a HTML table:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Our Books</title>
</head>
<body>
<table border="1">
<thead>
<tr>
{% for field in fields %}
<th>{{ field.verbose_name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr>
{% for field in fields %}
<td>{{ row[field] }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
Adding the header of the table works fine but this part is not working:
{% for row in rows %}
<tr>
{% for field in fields %}
<td>{{ row[field] }}</td>
{% endfor %}
</tr>
{% endfor %}
I have tried different things without any luck :
row[field]
row[field.verbose_name]
row.field
{{ row.__dict__.get(field.verbose_name) }}
- and more
How should I proceed? I do not want to hardcode the name of the columns in my template, I want to iterate over them so it would work with any table.
Solution
Django's template language does not support subscripting (i.e. x[y]
), this has been done deliberately to prevent people from writing business logic in the templates. One can use Jinja as a template language, but this is not necessary and to some extent counterproductive, precisely to prevent writing business logic in the template.
We can however "prepare" the data in the view, with:
def books(request):
fields = Book._meta.get_fields()
context = {
'rows': [
[getattr(book, field.name) for field in fields]
for book in Book.objects.all()
],
'fields': fields,
}
return render(request, 'blog/books.html', context)
and then render with:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Our Books</title>
</head>
<body>
<table border="1">
<thead>
<tr>
{% for field in fields %}
<th>{{ field.verbose_name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr>
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
Note: It might be worth to take a look at
django-tables2
[GitHub] to render tables in an effective way.
Answered By - willeM_ Van Onsem
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.