Search code examples
djangodjango-annotate

How to use percentage sign in annotate key


I'm trying to annotate a result column name with string that includes a percentage sign. This is the simplified code which can be run on any model basically:

from django.db.models import F

annotates = {'TEST %': F('id')}
SomeModel.objects.annotate(**annotates)[:1]

This produces error IndexError: tuple index out of range so I assumed Django is trying to do some formatting on that string and I tried putting double percentage sign 'TEST %%' to escape it which does not raise an error but it returns double spaces as column name which is not what I need.

Same result in Django 2.2 and 3.1

Is this a Django bug or I'm missing some known escaping sequence here?


Solution

  • You can not use % sign in annotation with F() or Cast() in Django.

    Because they have used the old string formatting in their methods (i.e. as_sql method with percentage sign formatting) and your error comes from the line return template % data, params in these methods and since you've inserted another percentage sign in to the default template it couldn't render it's template. It is not related to your SQL query or your database, and the only thing responsible for this error is the way that they have used for formatting the string. One way to skip this error is to change the line

    annotates = {'TEST %': F('id')}
    

    to

    annotates = {'TEST %%': F('id')}
    

    which tells your Python's interpreter to skip the percentage sign in formatting but note that in your annotation results you will have something like:

    {...other fields..., 'TEST %%': some id}