On Thu, 2007-08-23 at 21:59 +0800, Russell Keith-Magee wrote: [...] > 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.
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 %-) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---