Function to create an html table of a django queryset dynamically.
from django.urls import reverse,reverse_lazy, NoReverseMatch, resolve
from django.utils.safestring import mark_safe
from django.db.models.fields.files import ImageFieldFile, FileField
from decimal import Decimal
from django.utils.html import format_html
def get_rows(fields, object_list):
'''
fields : [{'verbose_name': 'Name', 'db_name': 'name'}]
object_list : queryset
'''
table = "<table class='table table-striped'>"
thead = '<thead><tr>'
for field in fields:
thead += f"<th>{field['verbose_name']}</th>"
thead += '</tr></thead>'
table += thead + '<tbody>'
for obj in object_list:
print(obj._meta.fields)
app = obj._meta.app_label
model = obj.__class__.__name__.lower()
update_url = reverse_lazy(f"{app}:{model}-update",kwargs={"pk":obj.pk})
delete_url = reverse_lazy(f"{app}:{model}-delete",kwargs={"pk":obj.pk})
tr = '<tr>'
for field in fields:
db_name = field['db_name']
value = getattr(obj, db_name)
if isinstance(value, Decimal):
value = round(value,0)
elif isinstance(value, bool):
if value:
value = format_html(mark_safe('<i class="bi bi-check-lg text-success"></i>'))
else:
value = format_html(mark_safe('<i class="bi bi-x-lg text-danger"></i>'))
elif isinstance(value, models.Manager):
print(f"{value} is a related manager.")
related_objects = value.get_queryset()
value = '<ul>'
for obj in related_objects:
value += f'<li>{obj}</li>'
value += '</ul>'
elif isinstance(value,ImageFieldFile):
if value and value.url:
value = format_html(mark_safe('<img src="{}" width="100px" />'.format(value.url)))
tr += '<td>' + str(value) + '</td>'
tr += f"""<td><a href='{update_url}'>{format_html(mark_safe('<i class="bi bi-pencil-square text-warning" style="font-size:1.5rem;"></i>'))}</a><a href='{delete_url} 'class='delete-tr'>{format_html(mark_safe('<i class="bi bi-x text-danger" style="font-size:1.5rem;"></i>'))}</a></td>"""
tr += '</tr>'
table += tr
table += '</tbody></table>'
return table