jieter / django-tables2

django-tables2 - An app for creating HTML tables
https://django-tables2.readthedocs.io/en/latest/
Other
1.89k stars 429 forks source link

FieldError when sorting getters #612

Open ccsv opened 6 years ago

ccsv commented 6 years ago

If I have a model with a getter like this:

class Species(models.Model):
    genus =models.ForeignKey(Genus, on_delete=models.CASCADE, blank=False, null = False)
    species = models.CharField(max_length=50, null=False, blank=False)
        ...
        @property
    def name(self):
              return self.genus.name +" "+ self.species

and if I use it in a table without setting the order-by field in the Column like this:

class SpeciesTable(tables.Table):
    name = tables.Column(accessor='name', verbose_name='Name')
       ...
        class Meta:
        model = Species
        template_name = 'django_tables2/bootstrap4.html'
        fields = ['name', ...]

The page will render fine but if I click on the column header I will get a FieldError: Cannot resolve keyword 'name' into field. This is resolved if I add something like order_by=('name') in tables.Column but by default there there is no ordering. Maybe set orderable=False for getter fields or have some kind of fallback solution?

jieter commented 6 years ago

So you suggest doing some inspection of the thing we get the data from and only set orderable=True if the column gets its data from a model field?

I didn't think this trough very well, but I suspect that might break the use case of rendering from a list of dicts.

ccsv commented 6 years ago

@jieter I think you might have a better idea than me.

mschoettle commented 4 years ago

I just ran into the same problem. However, the workaround with adding order_by='name' does not work for me. The FieldError shows me only the actual fields of the model in the error message.

The Django admin actually does not allow sorting fields that aren't actual database fields when they are added to list_display (see docs)

So by default, it should probably disable ordering.

How is sorting accomplished when the data does not come from a QuerySet?

mschoettle commented 4 years ago

As a workaround one could do the following:

# views.py
from django.views.generic.base import TemplateView
from django_tables2 import SingleTableMixin

class MyView(SingleTableMixin, TemplateView):
    template_name = 'myapp/myview.html'
    table_class = MyTable
    table_data = list(Model.objects.all())

However, all columns of the table must then be declared along with their verbose name (e.g., with Model._meta.get_field('fieldname').verbose_name).

I'm wondering if it would make sense to convert the QuerySet of the current page to a list to be able to use sort in the case that the order_by is not a field of the model?