views:

138

answers:

3

Using the standard Django templating system, is there any snippet/reusable template tag to have the first n words in a piece of text wrapped in a tag so I can style them?

What I'm ideally looking for:

{{item.description|wrap:"3 span big"}}

which outputs:

<span class="big">Lorem ipsum dolor</span> sit amet, consectetur adipiscing elit.

If this would be, for any reason, not feasible or really difficult to obtain, I can use JavaScript and do it client side, but I'd like more to be able to do it on page output.

+1  A: 

What's wrong with splitting out the first n words in the view function?

words = text.split()
head = ' '.join( words[:3] )
tail = ' '.join( words[3:] )

You provide head and tail to the template for rendering.

After all, that's what the view function is for.

S.Lott
+3  A: 

To be honest I didn't test this, but I guess it should work:

{% with item.description.split as desc %}
    <span class="big">{{ desc|slice:":3"|join:" " }}</span> 
    {{ desc|slice:"3:"|join:" " }} 
{% endwith %}

Update: it works now

Antony Hatchkins
This solution is "standard Django templating system, <...> snippet/reusable template tag", exactly as requested (thus can be suggested to designers) as opposed to author's own solution which is fine otherwise.
Antony Hatchkins
+1  A: 

It turns out that writing a filter is really easy (and works exactly the intended way).
This could be made a lot safer, but does the job (and won't break unless someone passes html as parameters):

from django import template
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe

register = template.Library()

@register.filter(name='wrap')
@stringfilter
def wrap(value, arg):
    params = arg.split()
    n = int(params[0])
    tag = params[1]
    tagclass = params[2]
    words = value.split()
    head = ' '.join( words[:n] )
    tail = ' '.join( words[n:] )
    return mark_safe('<%s class="%s">%s</%s> %s' % (tag, tagclass, head, tag, tail))
Agos