Trac user jbg has found a regression with the aggregation/annotation 
refactor #14030. The crux of the problem comes down to whether annotations 
and aggregations should respect constraints on model fields. The specific 
example raised is as follows:

Model.objects.aggregate(
    sum_price=Sum('price', output_field=DecimalField(max_digits=5, 
decimal_places=2)))

Assuming the field "price" is defined as "DecimalField(max_digits=5,
 decimal_places=2)", it doesn't matter if output_field is defined or not, 
as the implicit F('price') will result in exactly the same behaviour.

Each row in the table will adhere to the max_digits and decimal_places 
restriction. It has to, it's part of the column definition. But once you 
sum those values together, they are going to overflow. The same problem 
would exist if you were to concatenate two CharFields with a max_length=10.

Ticket https://code.djangoproject.com/ticket/23941 has been opened to track 
this.

These constraints do not necessarily make sense because we're not 
persisting these values anywhere. They are read-only computations, and 
should not require bounds. If these values were to be persisted in another 
model, then the input fields on that model are required to ensure the 
values are valid.

I've implemented https://github.com/django/django/pull/3655/ which 
effectively ignores the max_digits and decimal_places arguments in the base 
expression class. Subclasses are free to enforce validation if it is 
necessary. Further, callers using aren't required to supply bounds checking 
in this situation. This is valid (with my patch):

Model.objects.aggregate(
    sum_price=Sum('price', output_field=DecimalField()))

And the same goes with CharField() not requiring a max_length argument.

Can anyone see any issues with this approach?

If the above seems sensible, I'll alter the test cases to remove arguments 
like decimal_places and max_length, and update the documentation to call 
out that these kinds of arguments are not used for annotations.

Thanks,

Josh

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/6190d0fd-f1b3-4982-ada5-5520a7ee0e9d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to