Code

Opened 9 years ago

Closed 3 years ago

Last modified 18 months ago

#361 closed defect (wontfix)

Some Basic Math Filters

Reported by: ilikeprivacy@… Owned by: adrian
Component: Template system Version:
Severity: normal Keywords: filter math
Cc: dbrgn 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@… 6 years ago.

Download all attachments as: .zip

Change History (24)

comment:1 Changed 9 years ago by jacob

  • Resolution set to invalid
  • Status changed from new to closed

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 Changed 6 years ago by till@…

  • Resolution invalid deleted
  • Status changed from closed to reopened

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)

Changed 6 years ago by till@…

comment:3 Changed 6 years ago by jacob

  • Resolution set to wontfix
  • Status changed from reopened to closed

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 Changed 4 years ago by dloewenherz

"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 Changed 3 years ago by diramazioni

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 follow-up: Changed 3 years ago by anonymous

  • Resolution wontfix deleted
  • Status changed from closed to reopened

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

comment:7 in reply to: ↑ 6 Changed 3 years ago by lrekucki

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 Changed 3 years ago by lrekucki

  • Resolution set to wontfix
  • Status changed from reopened to closed

comment:9 Changed 3 years ago by anonymous

  • 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 follow-up: Changed 3 years ago by 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.

comment:11 in reply to: ↑ 10 Changed 3 years ago by anonymous

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 Changed 3 years ago by anonymous

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 Changed 3 years ago by adam.g.pullen@…

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 Changed 3 years ago by charettes

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

comment:15 Changed 3 years ago by anonymous

Thanks for the reply.

comment:16 Changed 2 years ago by Robert Wallner

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 Changed 2 years ago by anonymous

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 Changed 23 months ago by foxwhisper

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 Changed 23 months ago by foxwhisper

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 follow-up: Changed 19 months ago by will@…

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 %}

comment:21 in reply to: ↑ 20 Changed 19 months ago by ptone

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 Changed 19 months ago by dbrgn

  • Cc dbrgn 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 Changed 18 months ago by anonymous

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?

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.