Opened 12 years ago
Closed 11 years ago
#21565 closed Bug (fixed)
values() and values_list() don't work when datetime fields are specified and a GeoManager is used
| Reported by: | brett_energysavvy | Owned by: | |
|---|---|---|---|
| Component: | GIS | Version: | 1.5 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I've attached an app which can be used to reproduce this as well.
from django.db import models
from django.contrib.gis.db.models.manager import GeoManager
class MyModel(models.Model):
some_time = models.DateTimeField()
objects = GeoManager()
def some_function():
# Assuming there are instances of MyModel, this code will
# blow up when evaluated
list(MyModel.objects.values_list('id', 'some_time'))
This results in the following stack:
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 114, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Brett\Desktop\mysite\mysite\views.py", line 10, in repro_view
list(MyModel.objects.values_list('id', 'some_time'))
File "C:\Python27\lib\site-packages\django\db\models\query.py", line 96, in __iter__
self._fetch_all()
File "C:\Python27\lib\site-packages\django\db\models\query.py", line 854, in _fetch_all
self._result_cache = list(self.iterator())
File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1068, in iterator
for row in self.query.get_compiler(self.db).results_iter():
File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py", line 746, in results_iter
row = self.resolve_columns(row, fields)
File "C:\Python27\lib\site-packages\django\contrib\gis\db\models\sql\compiler.py", line 182, in resolve_columns
values.append(self.query.convert_values(value, field, self.connection))
File "C:\Python27\lib\site-packages\django\contrib\gis\db\models\sql\query.py", line 76, in convert_values
return super(GeoQuery, self).convert_values(value, field, connection)
File "C:\Python27\lib\site-packages\django\db\models\sql\query.py", line 289, in convert_values
return connection.ops.convert_values(value, field)
File "C:\Python27\lib\site-packages\django\db\backends\sqlite3\base.py", line 267, in convert_values
return parse_datetime_with_timezone_support(value)
File "C:\Python27\lib\site-packages\django\db\backends\sqlite3\base.py", line 46, in parse_datetime_with_timezone_support
dt = parse_datetime(value)
File "C:\Python27\lib\site-packages\django\utils\dateparse.py", line 67, in parse_datetime
match = datetime_re.match(value)
TypeError: expected string or buffer
This appears to also happen in Django 1.6. Any help on a workaround would be useful as well.
Attachments (2)
Change History (10)
by , 12 years ago
| Attachment: | mysite.zip added |
|---|
comment:1 by , 12 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
| Triage Stage: | Unreviewed → Accepted |
comment:2 by , 12 years ago
Have you had a chance to look at this? I can't seem to find a workaround for this and it's blocking our development team from upgrading to Django 1.5/1.6.
comment:4 by , 12 years ago
| Owner: | removed |
|---|---|
| Status: | assigned → new |
This bug only happens on Spatialite. Unfortunately I never managed to install it. I tried again tonight without success.
I wrote a test case, which I'm attaching. It passes under PostGIS.
by , 12 years ago
| Attachment: | 21565.diff added |
|---|
comment:5 by , 12 years ago
Python 3.3, Django@master, I believe the following is related, here is the traceback:
Traceback (most recent call last):
...
File "<virtualenv>/src/django/django/db/models/query.py", line 140, in __iter__
self._fetch_all()
File "<virtualenv>/src/django/django/db/models/query.py", line 962, in _fetch_all
self._result_cache = list(self.iterator())
File "<virtualenv>/src/django/django/db/models/query.py", line 267, in iterator
offset=len(aggregate_select))
File "<virtualenv>/src/django/django/db/models/query.py", line 1441, in get_cached_row
cached_row = get_cached_row(row, index_end, using, klass_info)
File "<virtualenv>/src/django/django/db/models/query.py", line 1429, in get_cached_row
obj = klass(*fields)
File "<virtualenv>/src/django/django/db/models/base.py", line 387, in __init__
setattr(self, field.attname, val)
File "<virtualenv>/src/django/django/contrib/gis/db/models/proxy.py", line 65, in __set__
obj.__class__.__name__, gtype, type(value)))
TypeError: Cannot set Location GeometryProxy (POINT) with value of type: <class 'bytes'>
Fix is easy for python 3; just add bytes to the list of types at django.contrib.gis.db.models.proxy line 60.
The weird thing is it only happens when testing, not on runserver.
comment:6 by , 12 years ago
Forget my comment above -- it is totally unrelated. I tried hard to find the cause of the error, but in the end I figured I'd forgotten to add the GeoManager to a custom intermediary ('through') model for the m2m relation, hence the exception. On the other hand, maybe I could create a ticket for the ugliness of the error above, for a user error that I'm sure is not that uncommon.
Excuse the noise from my part.
comment:7 by , 12 years ago
The problem is caused by resolve_columns in django/contrib/gis/db/models/sql/compiler.py, which calls self.query.convert_values if self.query.geo_values is True. However, the date value is already converted in a proper Python Datetime at the start of the method. It happens only in Spatialite because the basic convert_values don't touch date/time values, only the sqlite3 backend does. I see two ways forward:
- Just test in
parse_datetimethat the value is not already aDatetimeobject. - Try to be more clever at the
resolve_columnslevel to only callconvert_valueson geometry values (ORM knowledge required).
comment:8 by , 11 years ago
| Owner: | set to |
|---|---|
| Resolution: | → fixed |
| Status: | new → closed |
I haven't reproduced the problem yet but the use case is absolutely valid and the traceback proves the problem.
It's probably my fault :(