-
Notifications
You must be signed in to change notification settings - Fork 428
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Ordering by custom field raises an error #413
Ordering by custom field raises an error #413
Comments
Thanks for the bug report, it seems you did look into it a bit, can you maybe provide a test to reproduce the problem reliably? And maybe also a fix? |
Here is a simple test configuration to reproduce the problem:
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
class PersonTable(tables.Table):
first_name = tables.Column()
last_name = tables.Column()
full_name = tables.Column()
def render_full_name(self, record):
return record.last_name + ' ' + record.first_name
def order_full_name(self, queryset, is_descending):
queryset = queryset.annotate(
full_name=Concat(F('last_name'), Value(' '), F('first_name'))
).order_by(('-' if is_descending else '') + 'full_name')
return queryset, True
class Meta:
model = Person
fields = (
'first_name',
'last_name',
'full_name',
)
class PersonTestCase(TestCase):
def setUp(self):
self.factory = RequestFactory()
Person.objects.create(first_name="Alice", last_name='Beta')
Person.objects.create(first_name="Bob", last_name='Alpha')
def test_ordering_by_name(self):
request = self.factory.get('/?sort=first_name')
table = PersonTable(Person.objects.all())
RequestConfig(request, paginate=False).configure(table)
self.assertEqual(table.rows[0].record.first_name, 'Alice')
def test_ordering_by_custom_field(self):
request = self.factory.get('/?sort=full_name')
table = PersonTable(Person.objects.all())
RequestConfig(request, paginate=False).configure(table)
self.assertEqual(table.rows[0].record.first_name, 'Bob')
def test_ordering_by_both_with_custom_last(self):
request = self.factory.get('/?sort=first_name&sort=full_name')
table = PersonTable(Person.objects.all())
RequestConfig(request, paginate=False).configure(table)
self.assertEqual(table.rows[0].record.first_name, 'Bob')
def test_ordering_by_both_with_custom_first(self):
request = self.factory.get('/?sort=full_name&sort=first_name')
table = PersonTable(Person.objects.all())
RequestConfig(request, paginate=False).configure(table)
self.assertEqual(table.rows[0].record.first_name, 'Bob') The test Changing the def order_by(self, aliases):
'''
Order the data based on order by aliases (prefixed column names) in the
table.
Arguments:
aliases (`~.utils.OrderByTuple`): optionally prefixed names of
columns ('-' indicates descending order) in order of
significance with regard to data ordering.
'''
bound_column = None
modified_by_custom_order = False
accessors = []
for alias in aliases:
bound_column = self.table.columns[OrderBy(alias).bare]
# bound_column.order_by reflects the current ordering applied to
# the table. As such we need to check the current ordering on the
# column and use the opposite if it doesn't match the alias prefix.
if alias[0] != bound_column.order_by_alias[0]:
accessors += bound_column.order_by.opposite
else:
accessors += bound_column.order_by
if hasattr(self, 'queryset') and bound_column:
# Custom ordering
self.queryset, modified = bound_column.order(self.queryset, alias[0] == '-')
modified_by_custom_order = modified_by_custom_order or modified
if modified_by_custom_order:
return
# Traditional ordering
if accessors:
order_by_accessors = (a.for_queryset() for a in accessors)
self.queryset = self.queryset.order_by(*order_by_accessors)
else:
self.list.sort(key=OrderByTuple(accessors).key) |
@tjacoel thanks for your example. Your fix however, doesn't pass some of the other unit tests with the error |
* Added (failing) unit test for jieter#413 * Rough refactor of TableData into two different classes to declutter the ordering implementation * Move ordering related tests to separate file * Reorganize tests a bit * Fix jieter#413, ordering by custum field raises error
released 1.4.0 |
When defining a custom field in a table, as
name = tables.Column()
with methods to render and orderrender_name
andorder_name
, sorting by this column causes an error if the custom field is not in last position:/mytable?sort=name
works/mytable?sort=email&sort=name
works/mytable?sort=name&sort=email
raises a FieldError "Cannot resolve keyword u'name' into field"The cause of this problem is at https://github.com/bradleyayers/django-tables2/blob/master/django_tables2/tables.py#L108, this code is only called for the last column, whereas it should be checked for all columns.
The text was updated successfully, but these errors were encountered: