Opened 11 years ago
Closed 11 years ago
#24649 closed New feature (fixed)
Allow using the Avg aggregate on non-numeric field types
| Reported by: | Manuel Dominguez | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | josh.smeaton@… | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I am using the new DurationField and I tried to query the average value of that field but instead of returning any value the code raises a TypeError. The problem is that the Avg aggregate function tries to cast the returned value to float.
def convert_value(self, value, expression, connection, context):
if value is None:
return value
return float(value)
As the returned value is a timedelta the casting fails. I do not know if the right way to solve this is to allow to return timedeltas or use a new aggregate function just for DurationFields but I have solved with the latest.
class AvgDuration(Avg):
def convert_value(self, value, expression, connection, context):
return value
Change History (7)
comment:1 by , 11 years ago
| Keywords: | Avg DurationField removed |
|---|---|
| Summary: | Avg on DurationField raises TypeError. → Allow using the Avg aggregate on non-numeric field types |
| Triage Stage: | Unreviewed → Accepted |
| Type: | Bug → New feature |
| Version: | 1.8 → master |
comment:2 by , 11 years ago
Maybe even the convert_value method might be completely removed (as the default is using output_field already). At least, current tests don't seem to scream with that. Josh?
comment:3 by , 11 years ago
The float(value) is pretty much a direct port of the behaviour before expressions. It does need to be changed in some way though.
I'd have to run some tests, but I think there may be some issues if you try to take the Average of an IntegerField or a DecimalField without running convert_value. I'm not sure that the output_field is used for anything other than backend conversions.
I think we can get rid of the convert_value method, and add an output_field=FloatField into the constructor. Then to take the average of duration field:
.aggregate(Avg('duration', output_field=DurationField()))
Are there any other types that the AVG aggregate works with that doesn't return a float? If there are, we could probably think of a better all-round solution.
comment:4 by , 11 years ago
| Cc: | added |
|---|
The docs for
Avgsay "Returns the mean value of the given expression, which must be numeric." I am not an expressions expert, but it seems to me we could probably make it more generic based on the value ofoutput_field.