4

I'm using the build-in truncatewords_html filter of Django and it adds "..." in the end, instead, I want to replace this with a link "See More".

How can I achieve this?

Zach
  • 7,730
  • 3
  • 21
  • 26
Hellnar
  • 62,315
  • 79
  • 204
  • 279
  • possible duplicate of [How to find that the content is truncated?](http://stackoverflow.com/questions/1802625/how-to-find-that-the-content-is-truncated) – Ken Redler Mar 01 '12 at 18:57

3 Answers3

9

It would be best to write your own filter. You could take the source code for truncatewords_html and use it as a template for your filter. It should take a few changes to get what you want, and then you will just need to register your template and make sure you load it on the page you want to use it on and you should be good.

See this page for more info https://docs.djangoproject.com/en/dev/howto/custom-template-tags/

https://code.djangoproject.com/browser/django/trunk/django/template/defaultfilters.py#L288

You should be able to copy the method and just change the Code to this.

return Truncator(value).words(length, html=True, truncate=' see more')

You want to make 'see more' a link, that will take more code. I would change the filter to accept another param which is the link for 'see more'.

Then instead of just having 'see more' passed to Truncator you would pass the HTML link.

Zach
  • 7,730
  • 3
  • 21
  • 26
Ken Cochrane
  • 75,357
  • 9
  • 52
  • 60
  • Should be noted that the example code above refers to the latest dev version of Django I believe. It won't work with 1.3.1 as the `django.utils.text` library doesn't yet have the `Truncator` class. – Moz Morris Dec 18 '11 at 21:10
  • Good point, I got the code from trunk which is 1.4 code that is still in development. – Ken Cochrane Dec 18 '11 at 21:15
  • I had to double check - I thought for a second I was running old code. – Moz Morris Dec 18 '11 at 21:21
1

If you wanted to pass a custom link, that could be done like this.

Define your custom filter:

from django import template
from django.utils.safestring import mark_safe
from django.utils.text import truncate_html_words

register = template.Library()

@register.filter
def truncatewords_html_with_link(value, arg):
    """
    Truncates HTML after a certain number of words and concatenates a link

    Argument: String - Number of words to truncate after and the link, 
    separated by a comma
    """    
    arg_list = arg.split(',')
    try:
        length = int(arg_list[0])
    except ValueError:
        return value
    return mark_safe(truncate_html_words(value, length, arg_list[1]))

Call it from your template:

{{ text|truncatewords_html_with_link:"5, <a class=\"read-more\" href=\"/your_url/\">Read More</a>" }}
Moz Morris
  • 6,681
  • 2
  • 20
  • 18
  • I like what you have put together but it might be easier if you just pass in the URL to the filter and let the filter take the link and add the HTML, just and idea. – Ken Cochrane Dec 18 '11 at 21:12
  • Yeah, I think you're right. It's a little too messy trying to pass in the full html link. It's just that if you wanted to customise the 'Read More' link. – Moz Morris Dec 18 '11 at 21:20
  • Yeah I guess if you want to customize read more link you can pass that in as a second param and have it default to read more if not passed in – Ken Cochrane Dec 18 '11 at 21:36
0

The relevant code in Django 1.8 reads:

truncate = pgettext(
    'String to return when truncating text',
    '%(truncated_text)s...')

If you are using LOCALE and translation files, place the following into your *.po files:

msgid "String to return when truncating text"
msgstr "Short version: %(truncated_text)s <a class='see-more-link'>see more</a>"

Though, depending on what should happen when you click on the link adding it that way might not be very helpful. You could use another placeholder for it, but then you would have to make sure to replace the placeholder whereever this message string is used.

Risadinha
  • 16,058
  • 2
  • 88
  • 91