user55067
user55067

Reputation:

Django template ifequal comparison of decimals

So, I have a decimalfield that can be 3 different values. In my view, I pass in a dictionary of values that contains the appropriate decimal values as keys.

{% for item in booklist %}  
    {% for key, value in numvec.items %}  
        {{item.number}}  
        {% ifequals item.number {{key}} %}  
            {{value}}  
        {% endifequals %}  
    {% endfor %}
{% endfor %}

this is the dict I pass in as numvec:

numvec = {"TEST":Decimal("0.999"), "TEST2":Decimal("0.500"),

"TEST3":Decimal("0.255")}

the number field was defined as having these choices in my model:

BOOK_CHOICES=((Decimal("0.999"), 'TEST'),(Decimal("0.500"), 'TEST2'),(Decimal("0.255"), 'TEST3'),)

The item number prints out just fine in the view if I compare the dict with the attribute, but for some reason the ifequals cannot properly compare two decimals together. Is this a bug, or am I doing something wrong in my template with ifequals?

Upvotes: 1

Views: 11232

Answers (6)

Jacob CUI
Jacob CUI

Reputation: 1345

In contrast, numbers like 1.1 and 2.2 do not have exact representations in binary floating point. >>

E.g. if you

print Decimal(3.59)

you get

3.589999999999999857891452847979962825775146484375

So if you compare two decimals in django template, better to use the answer that @Oleg Sakharov has, or alternatively you can use same method but different formatting string like:

if item|stringformat:".2f" == "3.59"

Upvotes: 0

Drew
Drew

Reputation: 6639

The solution:

{% for item in decimals %}  
  {% if item|stringformat:"s" == variable %}  
    {{ variable }}
  {% endif %}  
{% endfor %}

works well for comparing a decimal (like the loop) to a string (like a passed value)

Upvotes: 2

Oleg Sakharov
Oleg Sakharov

Reputation: 1137

It is not a bug and it is possible to achieve what you're trying to do.

However, first of all few remarks about your code:

  • There is no "ifequals/endifequals" operator. You either use "ifequal/endifequal" or "if/endif".
  • Second thing. Your code {% ifequal item.number {{key}} %} would cause TemplateSyntaxError Exception if you leave double curly brackets inside the "ifequal" or "if" operator.

Now the solution:

  1. Just simply use "stringformat" filter to convert your decimal values to string.
  2. Skip curly brackets when you use variables inside operators.
  3. Don't forget that variable inside an "if" or "ifequal" operator is always represented as a string.

Here is an example:

{% for item in decimals %}  
  {% if item|stringformat:"s" == variable %}  
    {{ variable }}
  {% endif %}  
{% endfor %}

Upvotes: 11

Jehiah
Jehiah

Reputation: 2779

It's not quite clear if this would help Ardesco but there is template_utils which has if_greater, if_greater_or_equal, if_less, if_less_or_equal tags (among others) which solve very related cases where a plain ifequals isn't quite enough.

after installing just add template_utils do your django settings.py under INSTALLED_APPS and then put {% load comparison %} in your template

Upvotes: 0

Carl Meyer
Carl Meyer

Reputation: 126571

Simplest solution is to define a method on the model which encapsulates the numeric logic and returns the human-friendly string.

Or you can write a template tag to do it, which is a lot more code, but perhaps preserves the model/view layer separation a bit better.

Upvotes: 0

bchhun
bchhun

Reputation: 18474

According to this, it seems you can only compare strings. I'd make my own template tag if I were you.

Upvotes: 2

Related Questions