djangae
djangae copied to clipboard
Fix computed field pagination
Fixes #958
Summary of changes proposed in this Pull Request:
- Fixes bug in ordering of integer fields in pagination
- Adds support for paginating on negative integer fields
- Adds tests for int and char computed fields
PR checklist:
- [x] Updated relevant documentation
- [x] Updated CHANGELOG.md
- [x] Added tests for my change
Quick couple of thoughts (haven't had time to review in detail):
-
elif isinstance(value, float):
should just beelse
, because if the value is atimedelta
/boolean
/ whatever, then we should also blow up.- Possibly the previous
if
statement should also check forlong
.
- Possibly the previous
If we want to be Python 3.x friendly, use isinstance(x, numbers.Real)
instead of isinstance(x, (int, long, float))
or isinstance(x, numbers.Integral)
instead of isinstance(x, (int, long))
.
Is Python 3 compatibility a blocker to merging this?
No, there are lots of other non-python3-compatible things, so it shouldn't be a blocker.
However... when I run the tests on this branch locally, lots of the pagination tests fail with this same error:
ERROR: test_page_jump_updates_count_correctly (djangae.contrib.pagination.tests.DatastorePaginatorTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/aalton/Sites/github/djangae/testapp/djangae/contrib/pagination/tests.py", line 83, in setUp
self.u1 = TestUser.objects.create(id=1, first_name="A", last_name="A")
File "/Users/aalton/Sites/github/djangae/testapp/libs/django/db/models/manager.py", line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/aalton/Sites/github/djangae/testapp/libs/django/db/models/query.py", line 348, in create
obj.save(force_insert=True, using=self.db)
File "/Users/aalton/Sites/github/djangae/testapp/libs/django/db/models/base.py", line 734, in save
force_update=force_update, update_fields=update_fields)
File "/Users/aalton/Sites/github/djangae/testapp/libs/django/db/models/base.py", line 762, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/Users/aalton/Sites/github/djangae/testapp/libs/django/db/models/base.py", line 846, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/Users/aalton/Sites/github/djangae/testapp/libs/django/db/models/base.py", line 885, in _do_insert
using=using, raw=raw)
File "/Users/aalton/Sites/github/djangae/testapp/libs/django/db/models/manager.py", line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/aalton/Sites/github/djangae/testapp/libs/django/db/models/query.py", line 920, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/Users/aalton/Sites/github/djangae/testapp/libs/django/db/models/sql/compiler.py", line 973, in execute_sql
for sql, params in self.as_sql():
File "/Users/aalton/Sites/github/djangae/testapp/djangae/db/backends/appengine/compiler.py", line 68, in as_sql
self.query.raw), tuple())
File "/Users/aalton/Sites/github/djangae/testapp/djangae/db/backends/appengine/commands.py", line 643, in __init__
getattr(obj, field.attname) if raw else field.pre_save(obj, True),
File "/Users/aalton/Sites/github/djangae/testapp/djangae/fields/computed.py", line 13, in pre_save
value = self.get_computed_value(model_instance)
File "/Users/aalton/Sites/github/djangae/testapp/djangae/fields/computed.py", line 31, in get_computed_value
return self.computer(model_instance)
File "/Users/aalton/Sites/github/djangae/testapp/djangae/contrib/pagination/decorators.py", line 23, in generator
value = convert_to_paginatable_value(value, neg)
File "/Users/aalton/Sites/github/djangae/testapp/djangae/contrib/pagination/decorators.py", line 49, in convert_to_paginatable_value
value = u''.join([unichr(int(i)) for i in _chunks(str(value), n=5)])
ValueError: unichr() arg not in range(0x10000) (narrow Python build)
I'm guessing that Travis is running the "wide" python unicode build. But on the narrow one it dies.
Interesting, like Travis I'm also running a wide build which is why I hadn't come across this. Will check now!
When running the tests on my Mac, I'm now getting this (different test, same errorr):
ERROR: test_negatives (djangae.contrib.pagination.tests.ComputedIntegerFieldPaginationTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamalton/Sites/github/djangae/testapp/djangae/contrib/pagination/tests.py", line 275, in test_negatives
obj = ComputedIntegerFieldModel.objects.create(count=i)
File "/Users/adamalton/Sites/github/djangae/testapp/libs/django/db/models/manager.py", line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/adamalton/Sites/github/djangae/testapp/libs/django/db/models/query.py", line 348, in create
obj.save(force_insert=True, using=self.db)
File "/Users/adamalton/Sites/github/djangae/testapp/libs/django/db/models/base.py", line 734, in save
force_update=force_update, update_fields=update_fields)
File "/Users/adamalton/Sites/github/djangae/testapp/libs/django/db/models/base.py", line 762, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/Users/adamalton/Sites/github/djangae/testapp/libs/django/db/models/base.py", line 846, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/Users/adamalton/Sites/github/djangae/testapp/libs/django/db/models/base.py", line 885, in _do_insert
using=using, raw=raw)
File "/Users/adamalton/Sites/github/djangae/testapp/libs/django/db/models/manager.py", line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/adamalton/Sites/github/djangae/testapp/libs/django/db/models/query.py", line 920, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/Users/adamalton/Sites/github/djangae/testapp/libs/django/db/models/sql/compiler.py", line 973, in execute_sql
for sql, params in self.as_sql():
File "/Users/adamalton/Sites/github/djangae/testapp/djangae/db/backends/appengine/compiler.py", line 68, in as_sql
self.query.raw), tuple())
File "/Users/adamalton/Sites/github/djangae/testapp/djangae/db/backends/appengine/commands.py", line 643, in __init__
getattr(obj, field.attname) if raw else field.pre_save(obj, True),
File "/Users/adamalton/Sites/github/djangae/testapp/djangae/fields/computed.py", line 13, in pre_save
value = self.get_computed_value(model_instance)
File "/Users/adamalton/Sites/github/djangae/testapp/djangae/fields/computed.py", line 31, in get_computed_value
return self.computer(model_instance)
File "/Users/adamalton/Sites/github/djangae/testapp/djangae/contrib/pagination/decorators.py", line 24, in generator
value = convert_to_paginatable_value(value, neg)
File "/Users/adamalton/Sites/github/djangae/testapp/djangae/contrib/pagination/decorators.py", line 55, in convert_to_paginatable_value
value = u''.join([unichr(int(i)) for i in _chunks(str(value), n=5)])
ValueError: unichr() arg not in range(0x10000) (narrow Python build)
I noticed that this has been added:
if value is None:
return unicode(None)
but that will produce u"None"
, which is presumably not what we want?
I'm guessing that we should do:
if value is None:
return u""
?