Question

I'm new to Django and I'm building a web-page which displays model's info in a table format. I discovered for myself a very useful library - django-tables2 which makes building html tables very simple.

However, I am not able to figure out how to customize the rendering of one of the table columns. Specifically, I want a link column (I think it is implemented using LinkColumn or URLColumn in django_tables2) to render into

<a href="http://example.com">Personal Webpage</a>

instead of the django_tables2 way, where the link name is by default the link url.

<a href="http://example.com">http://example.com</a>

Where does this logic belong - in the model, in the view or in the template?

# models.py
class Person(models.Model):
  ...
  personal_webpage = models.URLField()
  #personal_webpage = models.URLField(display_link_name = "Personal Webpage") # is something like this possible at the model level?

# table.py
import django_tables2
import my_app.models import Person

class PersonTable(django_tables2.Table):
  class Meta:
    model = Person
    #personal_webpage = URLColumn(url_name = "Personal Webpage") # is something like this possible?

# views.py
from django.shortcuts import render
from django_tables2   import RequestConfig
from my_app.models    import Person
from my_app.table     import PersonTable

def personal_page_view(request):
  table = PersonTable(Person.objects.all())
  RequestConfig(request).configure(table)
  return render(request, "my_app/personal_webpage.html", {"table": table})

#personal_webpage.html
{% load render_table from django_tables2 %}
<!doctype html>
<html>

...

<body>

...

{% render_table table %}

</body>
</html>

I haven't yet looked into django/django_tables2 source code, and hopefully some will have a suggestion.

UPDATE: I searched around more for the solution, found a proposed solution:

#tables.py
class CustomTextLinkColumn(django_tables2.LinkColumn):

   def __init__(self, viewname, urlconf=None, args=None, 
     kwargs=None, current_app=None, attrs=None, custom_text=None, **extra):
     super(CustomTextLinkColumn, self).__init__(viewname, urlconf=urlconf, 
     args=args, kwargs=kwargs, current_app=current_app, attrs=attrs, **extra)

     self.custom_text = custom_text

     def render(self, value, record, bound_column):
       return super(CustomTextLinkColumn, self).render(self,
         self.custom_text if self.custom_text else value,
         record, bound_column)

class PersonTable(django_tables2.Table):

   webpage_link = CustomTextLinkColumn('my_app.views.personal_page_view', args=[A('personal_webpage')],
         custom_text='Personal Webpage', verbose_name='Personal Webpage', )

But it doesn't seem to work. The column gets rendered, but the cells of the column don't contain "Personal Webpage", and instead "---".

Was it helpful?

Solution

a little late answer, but you should change your PersonTable class like this:

class PersonTable(django_tables2.Table):
    personal_webpage = CustomTextLinkColumn('my_app.views.personal_page_view', 
        args=[A('personal_webpage')], custom_text='Personal Webpage', 
        verbose_name='Personal Webpage', )

    class Meta: 
        model = Person

The important (and not very clear) thing thing to keep in mind is that "render methods are only called if the value for a cell is determined to be not an empty value". Since your model does not have a webpage_link field or attribute, there's no value given to it. So you can either change the name to personal_webpage as I propose or pass the empty_values=() to your Column init as proposed in the answer to this question: Django Tables adding a LinkColumn / NoReverseMatch Error

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top