I have an app for example:
class example(models.Model, TemplateHelperClass):
reviewer = CharField(max_length=255, verbose_name="Title")
book = ForeignKey(books, on_delete=models.PROTECT)
review = TextField()
...
class books(models.Model, TemplateHelperClass):
author = CharField(max_length=255, verbose_name="Author")
book_title = CharField(max_length=255, verbose_name="Title")
publisher = CharField(max_length=255, verbose_name="Author")
def __str__(self):
return self.book_title
...
class templateHelperClass():
paginate_by = 15
def get_fields(self):
return [(field, field.value_to_string(self)) for field in self._meta.fields]
*views.py*
class bookReviewList(ListView):
model = example
template_name = "bookreviews.html"
...
*bookreviews.html*
{% extends "base.html" %}
{% block content %}
<table class="table">
<thead>
<tr>
{% for fld, val in object_list.0.get_fields %}
<th>{{ fld.verbose_name |title }}</th>
{% endfor %}
<th></th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
{% for fl1, val1 in object.get_fields %}
<td>{{val1}}</td>
{% endfor %}
<td><a class="btn btn-dark" href='{{ object.get_absolute_url }}'>Update</a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
The output html displays the pk for the book, and not the book title (the __str__
method) in this case. I'd like to display the __str__
method. Two questions, both related:
(1) Is there a more elegant way to represent the form with my attributes in table format. (I'm using bootstrap for some of the formatting)
(2) If not, how do I get the foreignkey field to display the __str__
return and not the pk?
The TemplateHelperClass
is a MixIn for multiple models and the equivalent template for bookreview.html
is likewise used for multiple views so I don't want to have to use specific field names in either if I can avoid it on the principle of DRY.
The easy solution is to use custom logic instead of field.value_to_string(...)
method
class templateHelperClass():
paginate_by = 15
def get_fields(self):
return [(field, str(getattr(self, field.name))) for field in self._meta.fields]
OR, use the custom logic only for FK field, as
class templateHelperClass:
paginate_by = 15
def get_fields(self):
return [
(field, str(getattr(self, field.name)))
if isinstance(field, models.ForeignKey)
else (field, field.value_to_string(self))
for field in self._meta.fields
]