Non-queryset data ordering in django-tables2
Asked Answered
G

1

12

The docs say:

Where the table is backed by a model, the database will handle the ordering. Where this is not the case, the Python cmp function is used and the following mechanism is used as a fallback when comparing across different types: ...

But is this possible in a table that is backed by a model, on a custom column? e.g.

class MyModel(models.Model):
    x = models.IntegerField()
    y = models.IntegerField()

    def z(self):
        return x+y

class MyTable(tables.Table):
    z = tables.Column()
    class Meta:
        model = MyModel

When I try something like this, the column displays OK, but when I click on the column header to sort, I get this error:

Caught FieldError while rendering: Cannot resolve keyword u'z' into field. Choices are: ...

Apparently this is because z is not found in the database table.

Is there a way around this?

Gryphon answered 14/6, 2012 at 1:30 Comment(2)
This is a bug/lack-of-feature in django-tables2. Would you mind adding an issue to github.com/bradleyayers/django-tables2/issues please? I've hit this myself recently but forgot to follow it up.Abutilon
Note that an issue was opened but this particular issue has not been fixed.Serviette
S
4

You can't use a queryset if you're ordering on an attribute that doesn't have a database column. You can pass a list to your table though.

Assuming your models.py looks like this:

from django.db import models

class MyModel(models.Model):
    def foo(self):
        return something_complex()

You could have tables.py that looks like this:

import django_tables2 as tables
from .models import MyModel

class MyModelTable(tables.Table):
    foo = tables.Column()

    class Meta:
        model = MyModel

Then in your views.py:

from django_tables2.config import RequestConfig
from django.core.paginator import InvalidPage
from django.shortcuts import render

def view_my_models(request):
    # use a list so django_tables2 sorts in memory
    my_models = list(MyModel.objects.all())

    my_models_table = MyModelTable(my_models)
    RequestConfig(request).configure(my_models_table)

    try:
        page_number = int(request.GET.get('page'))
    except (ValueError, TypeError):
        page_number = 1

    try:
        my_models_table.paginate(page=page_number, per_page=10)
    except InvalidPage:
        my_models_table.paginate(page=1, per_page=10)

    template_vars = {'table': my_models_table}
    return render(response, "view_my_models.html", template_vars)

There's also an open ticket discussing this issue.

Serviette answered 13/8, 2013 at 14:10 Comment(1)
converting the queryset to a list worked for me, thanks for that tip!Leix

© 2022 - 2024 — McMap. All rights reserved.