Search code examples
djangodjango-templatesforeign-keysdetailview

Get foreign key unicode value in the template rather than its id


My model consists of ForeignKey and I am using generics.DetailView to render object detail in the django view.

MyModel

class MyModel(models.Model):
    myField = models.ForeignKey(...)

    def get_fields(self):
        # called by the template
        return [(field.verbose_name, field.value_to_string(self)) for field in type(self)._meta.fields]

MyView

class Detail(DetailView):
    model = MyModel
    template_name = 'path/to/template.html'

    def get_context_data(self, **kwargs):
        context = super(Detail, self).get_context_data(**kwargs)
        # do something
        return context

And MyTemplate

{% for field, value in object.get_fields %}
           <tr>
               <th>{{ field }}</th>
               <td>{{ value }}</td>
           </tr>
{% endfor %}

Now when the template renders, what I get is id rather than __unicode__ representation. Same problem is seen for the ChoiceField as well(I get value rather than their labels).

So my question is, how can I get label or unicode representation rather than their actual values?


Solution

  • For ForeignKeys, getattr(self, field.name) seems to be working. So:

    class MyModel(models.Model):
        myField = models.ForeignKey(...)
    
        def get_fields(self):
            # called by the template
            return [(field.verbose_name, unicode(getattr(self, field.name))) for field in type(self)._meta.fields]
    

    For ChoiceFields, the label can be retrieved as self.get_<field_name>_display(). So, together, maybe something like

    class MyModel(models.Model):
        myField = models.ForeignKey(...)
    
        def get_field_value(self, field):
            if isinstance(field, models.CharField) and field.choices:
                 return getattr(self, 'get_{}_display'.format(field.name))()
            return unicode(getattr(self, field.name))
    
        def get_fields(self):
            # called by the template
            return [(field.verbose_name, self.get_field_value(field)) for field in type(self)._meta.fields]