Search code examples
pythondjangoaccessordjango-tables2

Ordering case insensitive in django-tables2


First post in this awesome community that I have been reading a long time ago :)

I've encountered with a problem when using this fantastic library "django-tables2". When I'm ordering a column by a CharField, it does a case sensitive ordering resulting unexpected behaviour like this:

Iago
Pablo
iago

I want to be ordered in a more natural way:

Iago
iago
Pablo

This is my simplified code for the table:

class Inquiry(models.Model):
    ...
    contact_last_name = models.CharField(max_length=50)
    ...

class Hometable(tables.Table):
    contact_last_name = tables.Column(verbose_name="Contact", order_by=('contact_last_name'))
    class Meta:
        model = Inquiry
        fields= ('contact_last_name',)

I know in Django 1.8 there is a built-in function Lower to make a insensitive order_by, but it doesn't work with django tables:

contact_last_name = tables.Column(verbose_name="Contact", order_by=(Lower('contact_last_name')))

It results in an exception:

TypeError at /
    'Lower' object is not iterable

Has anyone done anything similar with django-tables2?

Thank you!

UPDATE: The solution is to make a annotation in the view with the lowercase fields, an then will be available to order by in the table.

class Inquiry(models.Model):
    ...
    contact_last_name = models.CharField(max_length=50)
    ...

class Hometable(tables.Table):
    contact_last_name = tables.Column(verbose_name="Contact", order_by=('contact_last_name_lower'))
    class Meta:
        model = Inquiry
        fields= ('contact_last_name',)

And make the proper annotation in the queryset when configuring the table as Alasdair purposed:

inquiries = inquiries.annotate(contact_last_name_lower=Lower('last_name'))
my_table = Hometable(inquiries)

Solution

  • I haven't tried this, and I'm not really familiar with django-tables2 so I don't know whether it will work.

    You could try using a new field name e.g. contact_last_name_lower when setting order_by for the column.

    class Hometable(tables.Table):
        contact_last_name = tables.Column(verbose_name="Contact", order_by=('contact_last_name_lower',))
        class Meta:
            model = Inquiry
            fields= ('contact_last_name',)
    

    Then, when you instantiate the table, annotate the queryset with the lower case field.

    queryset = Inquiry.objects.annotate(contact_last_name_lower=Lower('contact_last_name'))
    table = Hometable(queryset)