Displaying verbose_name while using django-simple-history

Hi,

While using django-simple-history I would like to change the model fields name to display the verbose_name instead.

I know this topic has been discussed before (How to display verbose_name in HTML template). But I’m stuck and maybe someone can help me fix the issue that occurs.

I get this: AttributeError: 'str' object has no attribute '_meta' , and I’m not sure how to solve that issue.

My setup:
models.py:

from simple_history.models import HistoricalRecords

class Poll(models.Model):
    question = models.CharField(max_length=200, verbose_name="The question")
    pub_date = models.DateTimeField(verbose_name="Date Published ")
    history = HistoricalRecords()

    def __str__(self):
        return self.question

My views.py:

def history(request, poll_id):
    poll = Poll.objects.get(pk=poll_id)
    p = poll.history.all()
    
    changes = []
    if p is not None and poll_id:
        last = p.first()
        for all_changes in range(p.count()):
            new_record, old_record = last, last.prev_record
            if old_record is not None:
                delta = new_record.diff_against(old_record)
                changes.append(delta)
            last = old_record
    

    return render(request, 'django_history/historik.html', {
        'poll': poll,
        'changes': changes,
    })
    

My template:

<body>
    <h2>Test history: {{poll.question}}</h2>
    <h3>Changes made:</h3>
    <table>
        <thead>
            <tr>
                <th>id</th>
                <th>date/time</th>
                <th>change made</th>
                <th>user</th>
            </tr>
        </thead>
        <tbody>
            {% for change in changes %}
                <tr>
                    <td>{{change.new_record.history_id}}</td>
                    <td>{{change.new_record.history_date}}</td>
                    <td>
                        {% if change.changed_fields|length > 0 %}
                        {% for change_by_id in change.changes  %}
                        <b>{{change_by_id.field|verbose_name:change_by_id.field}}</b> From:
                        {% if change_by_id.old %}
                            <b>{{change_by_id.old}}</b>
                            {% else %}
                            <b>blank field</b>    
                        {% endif %}
                            to ---> <b>{{change_by_id.new}}</b>
                            <br>
                        {% endfor %}
                    {% else %}
                    There was no changes in this edition
                        {% endif %}
                    </td>
                    <td>{{change.new_record.history_user}}</td>
                </tr>
            {% endfor %}
                
        </tbody>
    </table>
        
</body>

My custom_tags.py:

from django import template

register = template.Library()

@register.filter
def verbose_name(poll, field_name):
    if poll._meta.get_field(field_name).verbose_name.islower:
        return poll._meta.get_field(field_name).verbose_name.capitalize()
    else:
        return poll._meta.get_field(field_name).verbose_name
    


If I change this line in the template: {{change_by_id.field|verbose_name:change_by_id.field}}
To: {{change_by_id.field|verbose_name}} I get this error:
django.template.exceptions.TemplateSyntaxError: verbose_name requires 2 arguments, 1 provided

So if I change that again -

To: <b>{{change_by_id.field|title}}</b> From: I see the model field names as is (Question / Pub_Date), but as mentioned above I’d like to see the verbose_name instead. So from the image below where “Question” is I’d like it to display “The question” as the verbose_name is in the model.

Little confused on how to solve it, maybe it’s a fairly easy fix (something I’m missing). Thanks for any help :slight_smile:

For something like django-simple-history, I’d consider a different solution.

I might take the approach of adding the verbose name to the history model and store it at the time the row is being saved. See Historical Model Customizations — django-simple-history 3.5.0.post4+g4d39103 documentation

But beyond that, if you look at that referenced post, what they’re passing to the filter is the object, not the field on the obect. In other words, it would be more something like:

{{change_by_id|verbose_name:change_by_id.field}}

(If change_by_id is the object for which you want the verbose name)

1 Like