Search code examples
pythonjinja2

How to convert a integer to ordinal string in python jinja templates


I want to replace 1 with 1st, 2 with 2nd, and so on, in the jinja template.

Currently, I'm using the following code, but it is throwing SyntaxError

{{ "%d%s"% (no_of_owners, "tsnrhtdd"[(no_of_owners|int//10%10!=1) * (no_of_owners|int%10<4) * no_of_owners|int%10 :: 4]) }}

where no_of_owners is a string like "5". What should be the correct way to achieve this result?


Solution

  • The error seems pretty clear:

    TypeError: %d format: a real number is required, not str
    

    You're trying to format a string using %d, which doesn't make any sense. You could simply replace it with %s:

    >>> t = jinja2.Template('''{{ "%s%s"% (no_of_owners, "tsnrhtdd"[(no_of_owners|int//10%10!=1) * (no_of_owners|int%10<4) * no_of_owners|int%10 :: 4]) }}''')
    >>> print(t.render(no_of_owners="5"))
    5th
    

    Or add the int filter:

    >>> t = jinja2.Template('''{{ "%d%s"% (no_of_owners|int, "tsnrhtdd"[(no_of_owners|int//10%10!=1) * (no_of_owners|int%10<4) * no_of_owners|int%10 :: 4]) }}''')
    >>> print(t.render(no_of_owners="5"))
    5th
    

    Update 1

    Here's a runnable version of the above examples:

    import jinja2
    
    print("=== using %s instead of %d ===")
    t = jinja2.Template('''{{ "%s%s"% (no_of_owners, "tsnrhtdd"[(no_of_owners|int//10%10!=1) * (no_of_owners|int%10<4) * no_of_owners|int%10 :: 4]) }}''')
    print(t.render(no_of_owners="5"))
    print()
    
    print("=== using int filter ===")
    t = jinja2.Template('''{{ "%d%s"% (no_of_owners|int, "tsnrhtdd"[(no_of_owners|int//10%10!=1) * (no_of_owners|int%10<4) * no_of_owners|int%10 :: 4]) }}''')
    print(t.render(no_of_owners="5"))
    print()
    

    I'm testing this using Jinja2 3.0.3 and Python 3.11.

    Update 2

    The above code also works with Python 3.6 and Jinja2 2.10.1:

    $ python
    Python 3.6.15 (default, Dec 21 2021, 12:03:22)
    [GCC 10.2.1 20210110] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import jinja2
    >>> jinja2.__version__
    '2.10.1'
    >>> t = jinja2.Template('''{{ "%s%s"% (no_of_owners, "tsnrhtdd"[(no_of_owners|int//10%10!=1) * (no_of_owners|int%10<4) * no_of_owners|int%10 :: 4]) }}''')
    >>> print(t.render(no_of_owners="5"))
    5th
    >>> t = jinja2.Template('''{{ "%d%s"% (no_of_owners|int, "tsnrhtdd"[(no_of_owners|int//10%10!=1) * (no_of_owners|int%10<4) * no_of_owners|int%10 :: 4]) }}''')
    >>> print(t.render(no_of_owners="5"))
    5th