I know my question could be a bit silly but... I dont know how to do
it. Do anybody know how to do arithmetic operations in a templete?
<a href="/client/{{ elem }}/{{ elem }}"> {{elem}} </a>
what I want to do is something like {{ elem }} + 100
thank you in advance.
There's an "add" filter...
http://www.djangoproject.com/documentation/templates/#add
{{ elem|add:100 }}
-tim
Generally speaking - you don't.
This is by design. Django tries very hard to prevent you from putting
logic into a template. Logic and calculations belong in the view; the
template shouldn't have any need for calculations. If you maintain
this strict separation, it becomes possible to change the template
without altering the view, and vice versa.
To this end, the Django template language is not, nor will ever be a
Turing complete programming language. We have specifically avoided
adding arithmetic operations, etc.
There are a few very basic math filters - but they exist only to
support display-based calculations. How many pixels wide does this DIV
need to be, given the size of its component parts - that sort of
thing.
If you think you need to do arithmetic in a template - think really
hard about what you are doing. Are you actually trying to change a
display feature, or are you changing the information that is being
displayed? If it is the latter, the calculation should be in the view.
Yours,
Russ Magee %-)
{% for i in name %}
{{ i_max}}
{% endfor %}
so I actually wants to print the value of a_max, b_max, etc. Is there
a way to do this? or I have to hardcode the code instead of using for
loop?
In your example, there's no need to pass in the list of names - you
are only iterating over the values. However, assuming that you
actually need the name: If a is related to a_max, then pass in context
data that expresses that relationship. Don't pass in two disconnected
lists - pass in a dictionary:
data = { a: a_max, b: b_max, ... }
Then in the template:
{% for key, value in data.items %}
{% key %} = {% value %}
{% endfor %}
Yours,
Russ Magee %-)
when i use
{% for key,value in data.items %}
{{key}}, {{value}}
{%endfor%}
it doesn't print anything, but when i do
{% for key in data.items %}{{key}}{%endfor%}
it prints :
('a', {'a_max': 9, 'a_min': 0, .... etc}),
did i pass the data incorrectly or something?
On Aug 24, 12:51 am, "Russell Keith-Magee" <freakboy3...@gmail.com>
wrote:
I neglected to mention that the key,value syntax is only in Django
trunk, not in 0.96. If you are using an older version of Django, you
will need to use
{% for item in data.items %}
{{ item.0 }} - {{ item.1 }}
{%endfor%}
> did i pass the data incorrectly or something?
In this case, Django is just following the instructions you gave.
> it doesn't print anything, but when i do
> {% for key in data.items %}{{key}}{%endfor%}
The loop here is for key in data.items:
data.items returns a list of tuples, so in this loop, each iteration
of 'key' will hold a key-value tuple:
> it prints :
> ('a', {'a_max': 9, 'a_min': 0, .... etc}),
Which is exactly what it prints.
Yours,
Russ Magee %-)
Hello,
Interestingly (to me, at least), I'm having issues with this very design
decision right now. Please bear with me, because this is a rather long
response.
While in general I agree with the whole "logic in views and display in
templates" idea, there are some very practical situations in which this
simply becomes a pedantic pain. And while in general Django is a very
nicely practical (yet still elegant) framework, I have to say I dislike
this approach quite a bit.
Here's why:
Let's say I have a set of objects, let's call them Parrots. Each Parrot
has an id, natch.
Now in my template, I'm building a list of these Parrots, and each row
in the list has a button that selects that Parrot when clicked. In
general, in the Javascript and HTML, this looks like this:
Button.create = function(id, label) {
some script to turn that DOM element into a DHTML button
}
<div class="parrotRow">
<span id="parrotButton-1"></span>
<script>Button.create('parrotButton-1', 'Choose me!');</script>
Hi, I'm the Parrot named Moe, and I'm #1!
</div>
<div class="parrotRow">
<span id="parrotButton-2"></span>
<script>Button.create('parrotButton-2', 'Choose me!');</script>
Hi, I'm the Parrot named Schmoe, and I'm #2!
</div>
And so on.
The template might look like this:
{% for parrot in parrots %}
<div class="parrotRow">
<span id="parrotButton-{{ parrot.id }}"></span>
<script>Button.create('parrotButton-2',{% trans 'Choose me!')</script>
Hi, I'm the Parrot named {{parrot.name}}, and I'm #{{ parrot.id }}!
</div>
{% endfor %}
All well and good. But now let's say I'm an appropriately (read:
responsibly) lazy programmer, and I wish to make a template tag that
outputs button code with a particular ID.
Easy, you say! {% myButton theId, 'Choose me!' %}, with the appropriate
Python code (and parsers, and so on) behind it.
As far as "Choose me!" goes, I can do the ugettext translation in the
tag, of course. However... the obvious problem becomes this: how do I
get "parrotButton-1" into theId? I don't want to hardcode
"parrotButton-" in the Python code, because when I have a list of tree
sloths on the same page, that won't make much sense (nor will it work if
we have both Parrot #1 and Sloth #1 on the same page).
I could write (or find) a tag that concatenates two strings, and places
the result in the context:
{% cat currentId "parrotButton-" parrot.id %}
{% myButton currentId %}
But what happens when I add other spanky new parameters to my button
tag, like "buttonText" and "buttonClass" and so on? Now I have to first
run a bunch of (possibly) specialized tags to put the values in the
context, and then call the myButton tag.
This reminds me horribly of the Bad Old Days of JSP, which I am
desperately trying to forget.
Ah, you say, but you're doing this wrong! Put this into your view code!
And here (finally) we get to my response to this thread: why on earth
would I put *template specific* code into my view? Now, instead of
having only some Javascript and a template that knows how to manipulate
it by creating the appropriate HTML, I have some Javascript, a template,
and a view that all have to know that the Javascript wants
"parrotButton-" + parrot.id... not only is this a pain, but it's a bad
idea. DRY and all that. Not only not only that, but I also have to
iterate my Parrots twice: once to set a bunch of constructed button IDs
somewhere, and once in the template to print them all out.
However, I don't *want* code in my view that knows about what my
Javascript and my HTML are doing in the first place. The string
"parrotButton-" + parrot.id has absolutely nothing to do with the data.
The view should keep its hands out of this. This is not logic, it's not
a calculation other than in the most remotest sense, and I'd really,
really like to keep this particular construction as close to where it is
used as possible. I also don't want a function on the Parrot itself that
knows to create "parrotButton-" + self.id... that's just silly. In fact,
my view code really shouldn't care if it's using an HTML template with
"Choose me!" buttons, an Excel template with a "Choose me!" macro, an
email with a "Choose me!" link, or a pigeon-carrier-wave cuneiform
tablet template with, er, "Choose me!" sticky notes made of Leicester
cheese and tar. It provides data, and whiz-bango
ala-peanut-butter-sandwiches-with-mayo, the *template* takes care of the
*formatting* specific to the task at hand.
Now what I'd like to do is this:
{% myButton '${"parrotButton-" + parrot.id}' %}
Problem sorted, and astute (but possibly mentally-scarred) readers who
have used a certain language and framework will note that this is how
JSP solved this particular problem: by adding the EL language to JSP
tags. Things got much simpler and nicer at that point in JSP Land (which
is still populated by a number of trolls, ogres, and generally
foul-smelling beasties, but at least not this particular foul-smelling
beastie). Tags encapsulate reusable logic, templates call those tags
with whatever they feel like, and life goes on quite smoothly as long as
the tags call the proper parsing routines to make sure the EL gets taken
care of.
Now since we're in Python Land (which for the most part is populated
only by a number of very pleasant and polite snakes), this should be
quite easy. In fact if I wanted to I'm sure I could come up with a
parser for my tag that ran every parm through a special "try to execute
this as Python" thinger. Well. That's what JSP went through... however,
the final, logical step, was to place that parsing *in the template
parser* so that every tag didn't have to be responsible for anticipating
how the template writer wished to use it. Et voila. Tags are easy,
templates are easy, and stuff gets reused where it ought to be reused.
Now of course, people could possibly misuse this functionality (*shock*
*horror*!) to do nasty things like writing Django templates to calculate
their income taxes. So? Let them. You're not their mother, they're big
boys and girls (if a bit daft), and the people who know enough not to
misuse such a feature to do their taxes will get on grandly by using it
properly to create selectable Parrots and Sloths instead.
Sorry for the long-winded semi-diatribe, but in my defense I've been
beating my head against this exact problem for a good while now. I'd
love to use template tags to reduce my repetition and reuse solid code
all over the place, but I'm being frustrated by this singular lack of
functionality. I will say this, however: it is only because the rest of
the Django template functionality is so darn good that I'm not just
throwing up my hands and using Cheetah or what have you. I love {%
extends %}, and filters, and being able to parse my tags any way I wish.
I just need a bit more...
What I'm hoping, however, is that this missive was moot, because you'll
say, "no, Scott, you should just do *this*:", followed by an elegant and
reasonable solution that I, as a relative newcomer to Django, have not
yet considered. Here's to your reply, and cheers!
Regards,
-scott anderson
> Yours,
> Russ Magee %-)
OK, here you go:
Use another template system, either site-wide or for the cases where
the Django template system isn't doing what you need. It's not hard to
do this, and it opens up the possibility of using any or all of the
vast number of Python template systems available.
The Django template system, at this point, will almost certainly
*never* include the type of functionality you're asking for, so use
another template system that does or that's more willing to bend its
philosophy to suit what you want. If you like the rest of the Django
template system I'd suggest you try Jinja, which started as a fork of
Django's template system and so is nearly feature-for-feature
identical, but adds arbitrary Python expressions.
--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."
In your Parrot model, you could add a property that displays your DOM
id.
class Parrot(models.Model):
# fields
def _domid(self):
return ''parrotButton-%s" % self.id
domid = property(_domid)
and use parrot.domid in your templates.
On 14 sep, 06:46, "James Bennett" <ubernost...@gmail.com> wrote:
Why should my *data model* know *anything* about the presentation? And
what happens when I want a parrot row ID, or a parrot foo ID, or a
parrot cheese ID? Suddenly I have a proliferation of things in my data
model that have jack all to do with the data, and everything to do with
a particular implementation of a particular view.
And then don't forget the Sloth Button ID as well... so if I have two
different data objects with similar presentation needs (but no other
similarities beyond that), I have to either a) introduce an inheritance
dependency that really makes no sense or b) duplicate a lot of code.
And then there's the fact that I can't use my nice generic button tag
with anything other than data that understands how it's supposed to be
displayed by a particular tag.
Regards,
-scott anderson
I'll look at Jinja, as I didn't realize there was such a fork.
Apparently I'm not the only one who thinks this way.
I'm concerned with how well a solution like this tracks the Django
release.
However, simply dodging the question doesn't address the original point:
why does Django adhere to such a nannyish philosophy, and how do you
solve the problem I presented *within Django* in a reasonable way?
Thanks and regards,
-scott anderson
Template tags really are the best place to put display-specific logic
like this. The original problem specified (a custom button and
associated JavaScript for an object with the object's name in the
button's id) could be solved using a template filter:
BUTTON_TEMPLATE = u"""<span id="%(type)sButton-%(id)s"></span>
<script type="text/javascript">
Button.create("%(type)sButton-%(id)s", "%(text)s");
</script>"""
def button(obj, text):
"""
Usage::
{{ some_object|button:"Choose me!" }}
"""
return BUTTON_TEMPLATE % {
'type': obj._meta.object_name.lower(),
'id': obj._get_pk_val(),
'text': ugettext(text),
}
button = register.filter(button)
If you wanted to have the button rendered from a template file, that
would be easy to add. Or if you wanted a different template file to be
used depending on the type of object (say, with each specialised
template inheriting from a generic button template), that would also
be pretty easy.
For the other options you went on to mention (including extra,
optional arguments), a "full" template tag would probably be in order.
You wouldn't have to place all the necessary data in the context first
as you stated - e.g. if you wanted to be able to specify a class for
the button, it wouldn't be too much work to implement a tag which can
sort this out:
{% button some_object "Choose me!" class=superButton %}
Jonathan.
Jonathan,
Thanks for the response. But to be fair to you I must disclose that I
anticipated that someone would present this as an answer. I would have
added this discussion into the original but it was already a bit
long... :-)
Here's the issue: while your solution works in this instance, it is
not a general solution to the problem.
So I have my Button template tag, and it allows both a type (or
discriminator, as I've been thinking of it) and an id, and it
arbitrarily mashes them together. So far, so good.
What if the next instance of a button needs an id that looks like
this?
parrotButton-{{ parrot.flock.id }}-{{ parrot.id }}
Or what if the text for the button is this?
Choose {{ parrot.name }}!
As you can see, the template tag code can quickly get arbitrarily
difficult and convoluted. Basically your solution requires that the
Button tag code anticipates every use to which it will ever be placed,
and this is one of the problems with this approach to which I object.
While you will always be able to present a specific solution to a
specific instance, your solution does not cover the general case which
leads to truly reusable template tag code.
Additionally, if we truly wish to allow the coding of templates by
people who are good at HTML, and leave the Python coding to the people
who are in turn good at Python, this sort of solultion requires the
template programmer to know Python in order to create tags that
reflect his or her needs. This is of course one of my main objections
to this approach: removing expressions from the template language
actually sabotages the main goal of separation of presentation and
logic.
> For the other options you went on to mention (including extra,
> optional arguments), a "full" template tag would probably be in order.
> You wouldn't have to place all the necessary data in the context first
> as you stated - e.g. if you wanted to be able to specify a class for
> the button, it wouldn't be too much work to implement a tag which can
> sort this out:
>
> {% button some_object "Choose me!" class=superButton %}
This solution generalizes to the case I mentioned in which the
template tags are responsible for parsing the expression language.
While it's possible to do this (and indeed I pointed this out in my
original post), it requires the template tag to be responsible for
anticipating how the tag will be used. While it is no doubt an
improvement, in the end the elegant solution is to allow the template
to responsible for this parsing so that even tags which do not
incorporate this special functionality can be used with expressions.
Now when I say expressions, I believe that at least 80% (if not more)
of my objections could be addressed by allowing the following sort
construct in template tags only:
{% mytag "${some.context.variable}-arbitrary-${other.variable}-text"
"Choose ${ parrot.name }!" %}
There... no dirty logic, no arithmetic, nothing really objectionable
as far as I can see with regards to the stated philosophy, but it
opens up a whole world of possibilities for the template designer that
are currently rather difficult and unnecessarily time-consuming to
accomplish. One could even place this in the split_contents function
to get halfway there, but I still believe it is most useful when
implemented by the template parsing system. I mean, even Velocity
allows this, and they're a good deal more dogmatic about it than the
Django folks seem to be.
> Jonathan.
Again, thank you for the response, and regards,
-scott anderson
Pesky kids these days, with your music and your anticipation...
> Now when I say expressions, I believe that at least 80% (if not more)
> of my objections could be addressed by allowing the following sort
> construct in template tags only:
>
> {% mytag "${some.context.variable}-arbitrary-${other.variable}-text"
> "Choose ${ parrot.name }!" %}
>
> There... no dirty logic, no arithmetic, nothing really objectionable
> as far as I can see with regards to the stated philosophy, but it
> opens up a whole world of possibilities for the template designer that
> are currently rather difficult and unnecessarily time-consuming to
> accomplish. One could even place this in the split_contents function
> to get halfway there, but I still believe it is most useful when
> implemented by the template parsing system. I mean, even Velocity
> allows this, and they're a good deal more dogmatic about it than the
> Django folks seem to be.
I agree that what you propose here would be useful in the scenario
you've described. *Personally*, if I wanted something like that, I'd
just write a function to do it and use it on my tag arguments.
Quick and dirty implementation (assuming the template library will
allow you to pass your example tag arguments as-is):
expression_re = re.compile(r'\$\{ *([a-z0-9\._]+) *\}')
expression_re.sub(resolve_variable(r'\1'), your_tag_argument)
> Again, thank you for the response, and regards,
> -scott anderson
Thanks for the interesting discussion, I only wish I had time to
participate in it properly. 5pm approaches :)
Jonathan.
:-)
> I agree that what you propose here would be useful in the scenario
> you've described. *Personally*, if I wanted something like that, I'd
> just write a function to do it and use it on my tag arguments.
>
> Quick and dirty implementation (assuming the template library will
> allow you to pass your example tag arguments as-is):
>
> expression_re = re.compile(r'\$\{ *([a-z0-9\._]+) *\}')
> expression_re.sub(resolve_variable(r'\1'), your_tag_argument)
But if you wanted to use that logic in a tag defined by someone else,
say, the url tag...
Regards,
-scott
Tsk, tsk. Bending the rules of the game a bit now, aren't we? :-)
Again, yes, you could do all of that. I'd rather not have to patch/
decorate/modify existing Django code for a specific application to do
it, however.
Regards,
-scott