django-pivot icon indicating copy to clipboard operation
django-pivot copied to clipboard

TypeError: annotate() keywords must be strings + FIX

Open corneliusabel opened this issue 4 years ago • 0 comments

First of all, thanks for the awesome package! Its really usefull!

I found a little bug in the pivot.py line 52. When i run pivot with the following parameters (models below):

pivot(Participant.objects.all(), 'language__name','languagelevel__level','id',Count)

I get the following error:

File "/django_pivot/pivot.py", line 41, in pivot
    values_list = queryset.values(*values).annotate(**annotations)
TypeError: annotate() keywords must be strings

This can be fixed by explicitly casting strings as keys for the returned dictionary:

def _get_annotations(column, column_values, data, aggregation, display_transform=lambda s: s, default=None):
    value = data if hasattr(data, 'resolve_expression') else F(data)
    return {
        str(display_transform(display_value)): Coalesce(aggregation(Case(When(Q(**{column: column_value}), then=value))), default)
        for column_value, display_value in column_values
    }

Should this be fixed in the code base or did I do something else wrong?

Best,

Cornelius


Relevant Models

class Participant(models.Model, ParticipantMailContextMixin):
    language = models.ManyToManyField(Language, through='LanguageLevel')

class LanguageLevel (models.Model):
    language = models.ForeignKey(Language, on_delete=models.CASCADE, verbose_name=_('Language'))
    participant = models.ForeignKey(Participant, on_delete=models.CASCADE)
    level = models.IntegerField(choices=LANGUAGELEVELCHOICES, blank=True, null=True, verbose_name=_('Level'))

class Language (models.Model):
    name = models.CharField(max_length=30, blank=True, null=True, verbose_name=_('Language'))

corneliusabel avatar Jan 21 '21 08:01 corneliusabel