Opened 19 years ago

Closed 14 years ago

Last modified 12 years ago

#361 closed defect (wontfix)

Some Basic Math Filters

Reported by: ilikeprivacy@… Owned by: Adrian Holovaty
Component: Template system Version:
Severity: normal Keywords: filter math
Cc: Danilo Bargen Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

This may be the wrong place to submit this...

I wanted some basic math filters (eg. add multiply divide subtract), there is already add so I created the others, no doubt probably the easiest filters I could create, though someone else may find them useful.

in django/core/defaultfilters.py

def mult(value, arg):
    "Multiplies the arg and the value"
    return int(value) * int(arg)

def sub(value, arg):
    "Subtracts the arg from the value"
    return int(value) - int(arg)

def div(value, arg):
    "Divides the value by the arg"
    return int(value) / int(arg)

template.register_filter('mult', mult, True)
template.register_filter('sub', sub, True)
template.register_filter('div', div, True)

Attachments (1)

filter_math.patch (1.3 KB ) - added by till@… 17 years ago.

Download all attachments as: .zip

Change History (24)

comment:1 by Jacob, 19 years ago

Resolution: invalid
Status: newclosed

The ticket system isn't the rigt place for this; feel free to create a wiki page for it for now; in the future we're going to have some sort of contributed apps repository for stuff like this.

comment:2 by till@…, 17 years ago

Resolution: invalid
Status: closedreopened

this is a very simple enhancement that would nicely blend into the set of django-supplied template filters.
(remember there is an add filter already)

maybe someone could reconsider inclusion of this trivial patch.

today it would look like this:

in django/template/defaultfilters.py

def mult(value, arg):
    "Multiplies the arg and the value"
    return int(value) * int(arg)
mult.is_safe = False

def sub(value, arg):
    "Subtracts the arg from the value"
    return int(value) - int(arg)
sub.is_safe = False

def div(value, arg):
    "Divides the value by the arg"
    return int(value) / int(arg)
div.is_safe = False

template.register_filter('mult', mult, True)
template.register_filter('sub', sub, True)
template.register_filter('div', div, True)

by till@…, 17 years ago

Attachment: filter_math.patch added

comment:3 by Jacob, 17 years ago

Resolution: wontfix
Status: reopenedclosed

Please don't reopen tickets marked closed by a committer. Take this to djangosnippets - it doesn't need to be part of Django.

comment:4 by Dan Loewenherz, 14 years ago

"add" is a filter, yet none of the other basic math operations are. This seems a little inconsistent to me.

it doesn't need to be part of Django.

And yet something like "ipsum lorem dolor sit amet" does? I think this deserves a 2nd look.

comment:5 by diramazioni, 14 years ago

As newcomer to django I find really weird there is no math operations or the elseif operator in the template system. They are so common in others... Nobody willing to explain why there are such limitation?

comment:6 by anonymous, 14 years ago

Resolution: wontfix
Status: closedreopened

Django runs it's shop like the Third Reich... ADD MATH FILTERS

in reply to:  6 comment:7 by Łukasz Rekucki, 14 years ago

Replying to anonymous:

Django runs it's shop like the Third Reich... ADD MATH FILTERS

Your behavior doesn't really deserve a comment, especially that you were brave enough not to sign it with your name. Normally people discuss this kind of stuff on the developers list, but I'm not sure if I want to discuss with this kind of offensive comments.

comment:8 by Łukasz Rekucki, 14 years ago

Resolution: wontfix
Status: reopenedclosed

comment:9 by anonymous, 14 years ago

Easy pickings: unset
UI/UX: unset

it doesn't need to be part of Django.

May I know why it according to you doesn't need to be part of Django? Every time I find myself writing these filters yet again I have the oposite impression. There are situations where not having the ability to do basic math in templates results in code that is more complicated (thus error prone) and longer to write then it would otherwise be necessary. I find this unwillingness to include something as basic and harmless as these filters are rather absurd.

comment:10 by Russell Keith-Magee, 14 years ago

This topic has been discussed repeatedly on django-dev and django-users. The reasoning *isn't* absurd -- it's part of the fundamental design intent of the template language. The reasoning is that Django's template language shouldn't encourage putting business logic in templates. Providing extensive tools for in-template math would encourage the placement of business logic in templates.

in reply to:  10 comment:11 by anonymous, 13 years ago

Replying to russellm:

This topic has been discussed repeatedly on django-dev and django-users. The reasoning *isn't* absurd -- it's part of the fundamental design intent of the template language. The reasoning is that Django's template language shouldn't encourage putting business logic in templates. Providing extensive tools for in-template math would encourage the placement of business logic in templates.

Django templates is the most inconsistent and horrible templating language available. Can you not just switch to Jinja2 and be done with it?
I want to add two datetimes together in my template. Nice, now I have to do it in several places in my code. Not good.

comment:12 by anonymous, 13 years ago

Unfortunately, your criticism lacks details that would allow us to understand your problem and actually improve the template language.

I think template tags are appropriate for the use case you're describing.

comment:13 by adam.g.pullen@…, 13 years ago

Here is sample code where simple math in the template engine may make sense.
It is totally presentation related.
This post should not be taken as critizam, more as developers trying to improve the framework.

We have a list of items that need to be displayed in a "3*n" table

There are 2 issues

1) Primary Issue: The forloop.counter starts at 1 which, depending on how you look at it, is wrong. It should, to remain consistant with python and most other languages, start at 0.

2) Due to the lack of the simple math functions (requirement driving from incorrect forloop.counter value) I will have to try to implement the code listed above.

{% comment %}
  Counter is used to perform the "row grouping" when mod 3 == 0 then a new row is started
  When counter is > 0 then the row is ended
{% endcomment  %}
{% for item in items %}
            {% if counter|divisibleby:3 or forloop.counter == 1 %}
                  {% if forloop.counter > 1 %}
                        </div>
                  {% endif %}
                  <div class="creator_gallery_row">
            {% endif %}
      {% include "terra_creator/gallery_item.html" %}
{% endfor %}

Just a note for reference: divisibleby "DOES need to be part of Django" but multiplication not?



Ok durring writing this i found that

forloop.counter|add:"-1"|divisibleby:3

will solve my problem



I still think that you should listen to your users. It up to them to decide if they want to "bastardise" their application by putting application logic into the view, not the framework.

comment:14 by Simon Charette, 13 years ago

Adam, you should try forloop.counter0 instead of forloop.counter|add:"-1"|divisibleby:3.

comment:15 by anonymous, 13 years ago

Thanks for the reply.

comment:16 by Robert Wallner, 13 years ago

I think this is a common misconception. Business logic code doesn't belong in the template, but at the same time, template logic doesn't belong in the code. So, not having arithmetic operations in the template do exactly the opposite. It encourages users to put the template logic inside their code, which is as bad as placing business logic code inside templates. Reminds me of Ocam's razor :)

comment:17 by anonymous, 13 years ago

I know this is not the place, but I have to say it. It would be nice to be able to do things like:

<div style="padding-top: {{ 200 - thumb.heigth }}">
  <img src="{{ thumb }}">
</div>

comment:18 by Cal Leeming, 13 years ago

Today I found the need for having math filters in the template, specifically for visualization (changing 0.01PPM into 1p) which is not business logic but indeed template logic.

Just as I was about to add a comment saying "omfg why doesn't Django support this", I realized why the core devs are rejecting this. And the simple reason is, it would get abused like crazy and it's would be a slippery path to failure. Sure it would be useful for sane developers on specific use cases, but it would be abused by the majority.

Although Adam makes a good point with this comment:

It up to them to decide if they want to "bastardise" their application by putting application logic into the view, not the framework.

dloewenherz also makes another good point:

"add" is a filter, yet none of the other basic math operations are. This seems a little inconsistent to me.

Could a core developer perhaps explain what the reasoning was behind having add, but not any of the others?? I had a look around the archives, but couldn't seem to find any justification for this. It seems to me that we should either have all of them, or none at all??

It seems this topic hits a nerve with a lot of people, so if a core dev is able to give some answers on the above, we will finally be able to put this issue to rest with a concrete justification.

comment:19 by Cal Leeming, 13 years ago

As a side note, if math filters were to ever get accepted into the core, it would be so much better if they weren't as template tag filters, but instead as native expressions with nested support:

For example:

{{ (someval * 10) + 5 }}

comment:20 by will@…, 12 years ago

I would like to have a "subtract" filter for this use case:
I want to only show the first 10 items in a list, then have a final line saying how many other items there were,
E.g.
"And 3 other items..."

This is purely a display (template) logic, so it should be supported by the template language (same as 'add').

{% for l in list_items %}
    {% if forloop.counter < 10 %}
        <li>l </li>
    {% else %}
        {% ifequal forloop.counter 10 %}
            <li>
                And {{ list_items|length|subtract:10 }} other objects...
            </li>
        {% endifequal %}
    {% endif %}
{% endfor %}

in reply to:  20 comment:21 by Preston Holmes, 12 years ago

Replying to will@…:

I would like to have a "subtract" filter for this use case:

If you feel you have a display related argument here - you are better off opening a new ticket than posting a comment on a very old wontfix ticket.

If you choose to do so, please explicitly reference this ticket, and explain why you think it is a different circumstance.

comment:22 by Danilo Bargen, 12 years ago

Cc: Danilo Bargen added

As a workaround, I created a separate Django app containing "sub", "mul", "div" and "abs" filters: https://github.com/gwrtheyrn/django-mathfilters

will@..., you could also add -10 instead of subtracting 10 in your case: list_items|length|add:-10

comment:23 by anonymous, 12 years ago

I also have a case where I feel that the logic should rest in the template, not in the code.

I have posts that have variable parent-child levels and I need to add padding to them according to their level. Should I really do "padding = level * 50" in my view code?

Note: See TracTickets for help on using tickets.
Back to Top