
front and back-end web development, Leeds, UK
Richard's Blog - Design, coding and life in Japan
Creating Rails like template helpers in Django
Submitted by Richard on Thu, 06/24/2010 - 22:01I wanted to make some easy link helpers so that I could have customized rounded corner links without needing JS and so that I could change them easily later if I needed to. This is so easy in Rails it is just crazy trivial. This was not the case in Django, and even though I believe it should be easier (and I believe it is easier with a little help with a method here and there). I tried to do it the real way. By making a custom tag.
First the Rails way, just add the following to application_helper.rb
def blue_link(url, text)
"<span class='blue-link'><a href='#{url}'>#{text}</a></span>"
endThen add to your template
<%= blue_link(new_user_path, "Sign Up Here!") %>
This is so easy it is crazy!, now for the Djano one, hold your breath! I wanted to add the following style of tag to my template,
{% bluelink 'Sign up here' %}{% url project.users.views.create %}{% endlink %}Seems like it should be easy enough right? First I added an 'extras' app to handle my extra bits and pieces -make sure you include your '__init__.py', within that app I created a directory 'templatetags' which also contains our main tag file 'helper_tags.py' with that directory also containing a '__init__.py' file. I also needed to add 'project.extras' to INSTALLED_APPS in my 'settings.py'
Here is what I have in my 'helper_tags.py'
from django import template
class BlueLinkNode(template.Node):
def __init__(self, text, url):
self.text = text
self.url = url
def render(self, context):
return '<span class="blue-link"><a href="'+ self.url.render(context) + '">'+ self.text + '</a></span>'
def do_bluelink(parser, token):
url = parser.parse(('endlink',))
parser.delete_first_token()
text = token.split_contents()[1][1:-1]
return BlueLinkNode(text, url)
register = template.Library()
register.tag('bluelink', do_bluelink) Now if I add
{% load helper_tags %}To my template I can finally use my helper tag.
Although creating a helper like the above frustrated the hell out of me, and the syntax was so sensitive to every include and move. There is still so much that I love about Django which makes me want to carry on using it as one of my main development tools. But I think we can learn from the simplistic beauty of Ruby on Rails. Saying that I am a relative newbie to Python/Django and would love your feedback. If there is an obvious easier way to do this please get back to me!.
Tags:
Recent Blog Posts
- Testing controllers in Lithium 2nd Feb 12, 18:19
- Practical Internationalization in Lithium 31st Dec 11, 02:06
- Using OAuth in Lithium 30th Dec 11, 23:47
- How to add your own Tokens from CCK fields in Druapl 7 17th Jun 11, 04:49
- Weaving Lithium #li3 into a legacy PHP application incrementally 5th Oct 10, 11:54
The right way...
You could just use :
in your template :
{% url project.users.views.create as the_url %}
{{ the_url|bluelink:"Sign up here" }}
in your .py
@register.filter
def bluelink(value, arg):
return '<span class="blue-link"><a href="%s">%s</a></span>' % (value, arg);
Please read the docs.
Thanks.
Thanks for the suggestion,
Thanks for the suggestion, but I personally don't like adding hard coded html inside of python methods. It feels a little dirty and is harder to maintain.
Shorter and more elegant way,
Shorter and more elegant way, without Python code. ::
{% url project.users.views.create as the_url %}
{% include "my_blue_link_template.html" %}
my_blue_link_template.html ::
{{ the_url }}
Unfortunately you can then
Unfortunately you can then not place in business logic that maybe needed to process the output further.
Ahem.
Why the hell would you want a templatetag to generate some span tag? Come on, please take another example, you just took a bazooka to kill a mosquito here.
Generally playing with {% if %} and/or some filters is enough for such a simple caseā¦
Yes I agree that is my point!
If you can do it easily and simply great, but you can't. In Rails you can do it so simply.
I was wanting to make a quick helper method to add an extra span for links with round corners which may change in future. If I want to go and change all of the tags that have {% if %} etc wrapped around them then that is a big pain in the arse.
Not being able to add simple tags easily in Django is a big downfall of the framework. Which is why Roger even suggested using a different framework.
What I was really fishing for was an easier way of doing this...
Thanks for the feedback though....
web2py
You might like web2py with its (to me) easier layout.
Roger, thanks for the tip, I
Roger, thanks for the tip, I will look into that!
I was also going to check out turbo gears at some point, but any advice is appreciated!
Cheers
Post new comment