Search code examples
pythondjangodjango-modelsdjango-views

Use annotated values as value in when()


I try to use a calculated value with annotated fields in the "then" parameter of a When(). Django raise me an error:

can't adapt type 'CombinedExpression'

Here is my code:

categories = Category.objects.filter(
            Q(amount__card__date__range=(
                start_day_compare,
                stop_day_compare
            )) | Q(amount__card__date__range=(
                previous_start_day_compare,
                previous_stop_day_compare
            ))
        ).annotate(
            somme=Sum(
                'amount__amount',
                filter=Q(
                    amount__card__date__range=(
                        start_day_compare,
                        stop_day_compare
                    )
                )
            )
        ).annotate(
            previous_somme=Sum(
                'amount__amount',
                filter=Q(
                    amount__card__date__range=(
                        previous_start_day_compare,
                        previous_stop_day_compare
                    )
                )
            )
        ).annotate(
            evolution=Case(
                When(
                    ~Q(previous_somme=0),
                    then=Value(
                        (
                            (
                                Sum(
                                    'amount__amount',
                                    filter=Q(
                                        amount__card__date__range=(
                                            start_day_compare,
                                            stop_day_compare
                                        )
                                    )
                                ) - Sum(
                                    'amount__amount',
                                    filter=Q(
                                        amount__card__date__range=(
                                            previous_start_day_compare,
                                            previous_stop_day_compare
                                        )
                                    )
                                )
                            ) * 100
                        ) / Sum(
                            'amount__amount',
                            filter=Q(
                                amount__card__date__range=(
                                    previous_start_day_compare,
                                    previous_stop_day_compare
                                )
                            )
                        )
                    )
                ),
                default=Value('N/A'),
                output_field=CharField()
            )
        ).order_by(
            'order'
        )

So I try to annotate as "evolution" a percentage of evolution between previous_somme and somme. But when previous somme is 0 I don't want to do the calculation (because of division by zero). But it seems impossible to do calculation inside the Value. I tried to use directly "somme" and "previous_somme" but they are not reconized.

Do you have an idea to do this? Thanks

PS: the rest of the request works, when I put a 1 in the Value it works fine.


Solution

  • I didn't quite understand the question but I think changing the When part to something like this should do the work:

                When(
                    ~Q(previous_somme=0),
                    then=(
                        ((models.F('somme') - models.F('previous_somme')) * 100) / models.F('previous_somme')
                    )
                ),
                default=Value('N/A'),
                output_field=CharField()
            )