Opened 13 years ago
Closed 13 years ago
#19360 closed Bug (fixed)
annotate the sum of related TimeField
| Reported by: | Luc Saffre | Owned by: | chrismedrela |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | chrismedrela | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I get a "TypeError: expected string or buffer" when I try to annotate the sum of a timefield in a related model.
class Ticket(models.Model):
name = models.CharField(max_length=200)
class Session(models.Model):
ticket = models.ForeignKey(Ticket,related_name="sessions")
time = models.TimeField()
qs = Ticket.objects.annotate(timesum=models.Sum('sessions__time'))
print [unicode(t.timesum) for t in qs]
Please see the attached files for a complete test case.
Attachments (2)
Change History (10)
by , 13 years ago
| Attachment: | 20121124.zip added |
|---|
comment:1 by , 13 years ago
| Cc: | added |
|---|---|
| Component: | Uncategorized → Database layer (models, ORM) |
| Triage Stage: | Unreviewed → Accepted |
| Type: | Uncategorized → Bug |
| Version: | 1.4 → master |
comment:2 by , 13 years ago
| Owner: | changed from to |
|---|
The problem is that django.utils.dateparse.parse_time function is called with float argument instead of string. Then the argument is passed on to re_pattern.match function.
comment:3 by , 13 years ago
The problem is that there is no native time field in sqlite. This feature is emulated by Django -- the time is saved as text (HH:MM:SS). The query
Ticket.objects.annotate(timesum=models.Sum('sessions__time'))
is translated into the following SQL statement:
SELECT ..., SUM("polls_session"."time") AS "timesum" FROM "polls_ticket" LEFT OUTER JOIN ...
The sum expression doesn't make sense since "polls_session"."time" is a text column, but it fails silently -- the sum returned by sqlite3 driver is 0.0 float. Then Django try to parse the result as a time using re module, but the result it's not even string which causes raising the exception.
What can we do? We can use integer column representing unix time to emulate date/time fields, but it's lot of work and it breaks backward compatibility. We should at least add note to documentation. Django should fail loudly when you try to aggregate date/time fields in sqlite. Any other ideas?
by , 13 years ago
| Attachment: | 19360_v1.diff added |
|---|
comment:4 by , 13 years ago
| Has patch: | set |
|---|
I've written a patch (and created pull request -- see https://github.com/django/django/pull/579). It raises an explicit exception if you aggregate on date/time field in sqlite3. Are tests required for fixes like that?
comment:6 by , 13 years ago
| Needs tests: | unset |
|---|
Added tests and documentation. New pull request here: https://github.com/django/django/pull/637.
comment:7 by , 13 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
comment:8 by , 13 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
2 files models.py and settings.py