Hi Russell, Unfortunately, I don't think your ticketing system likes me. I'm getting: 500 Internal Server Error (Submission rejected as potential spam).
Here's the text of the ticket. If anyone can post it up for me, I'd be grateful. Thanks! Aral The truncatewords filter currently adds faux ellipses (three dots) to every truncated string. This is not ideal for several reasons: 1. It should use a true ellipsis (\u2026) instead of three dots. 2. The filter would be far more useful if adding ellipses was an _option_. Use case for number 2: I have a person's full name: "Aral Balkan" and I want to greet them by their first name. I should be able to write the following in a template to indicate that an ellipsis should not be added: {{{ Hello, {{personName|truncatewords:1:False}}, how are you? }}} The truncatewords filter would simply have its signature altered and call utils.text.truncate_words with the altered signature, passing the second argument: {{{ def truncatewords(value, arg, add_ellipsis=True): """ Truncates a string after a certain number of words. Argument: Number of words to truncate after. And, (optional) whether or not to add an ellipsis. """ from django.utils.text import truncate_words try: length = int(arg) except ValueError: # Invalid literal for int(). return value # Fail silently. return truncate_words(value, length, add_ellipsis) }}} And utils.text.truncate_words would be changed to: {{{ def truncate_words(s, num, add_ellipsis=True): "Truncates a string after a certain number of words." s = force_unicode(s) length = int(num) words = s.split() if len(words) > length: words = words[:length] if add_ellipsis: if not words[-1].endswith(u'…'): words.append(u'…') return u' '.join(words) }}} Since we're using a unicode literal, utils.text would also have to specify the encoding: {{{ # This Python file uses the following encoding: utf-8 }}} Unfortunately, we don't have multiple arguments in filters, so the above will not currently work. However, because this is an actual use case, I do need to implement this somehow and my options are either to: 1. Handle the truncation in my view and pass only the first name. This leads to duplication of code. And it's debatable how much this code actually belongs in my view function. 2. Write a separate filter (truncatewordswithoutellipsis) with an inelegant name and result in duplication of code. 3. Have truncatewords accept a string and parse it using a delimiter. (If having multiple arguments is seen an overly-complex for filters, this is doubly so as it makes the syntax way more confusing by robbing the integer length argument and the boolean add_ellipsis argument of their actual datatypes and thus weakening the intent of the code). 4. Create a convention that works with the current system and only requires one argument. In this case, I decided to go with number 4 and create the following convention: If the argument provided to truncatewords is positive, it ads ellipsis, if it is negative, it does not. {{{ Hello, {{personName|truncatewords:1}}, }}} Hello, Aral ..., {{{ Hello {{personName|truncatewords:"-1"}}, }}} Hello, Aral, Of course, this solution is quite ridiculous and the syntax is in no way intuitive. It is a direct result of the artificial constraint of not being able to use more than one argument in a filter (and not the template-author's needs). Within the current rules for filters, however, it makes complete sense and may even be seen as an elegant solution given the one-argument constraint (which is to say that, ipso facto, the current constraint does not make much sense.) I am aware of and completely agree with Django's philosophy of keeping templates simple but, in this case, the limitation of having just one argument for a filter actually _complicates_ templates more than if filters could take more than one argument. The refactored truncatewords filter from the solution above is below and uses the utils.text.truncate_words function listed earlier: {{{ def truncatewords(value, arg, add_ellipsis=True): """ Truncates a string after a certain number of words. Argument: Number of words to truncate after. And, (optional) whether or not to add an ellipsis. """ from django.utils.text import truncate_words try: length = int(arg) except ValueError: # Invalid literal for int(). return value # Fail silently. if length<0: add_ellipsis = False; length = abs(length) return truncate_words(value, length, add_ellipsis) }}} Please feel free to commit this (diffs at end) if you feel that having words truncated without ellipses is a use case that other developers may have also. However, I do hope instead that we can address the bigger problem here which is this: Filters are currently artificially constrained to have a single argument and this is making it difficult to create elegant solutions for certain legitimate use cases. This constraint runs contrary to Django's philosophy of keeping the templating system simple by resulting in complicated workarounds that muddy the intent of the resulting code. {{{ =================================================================== --- text.py (revision 7568) +++ text.py (working copy) @@ -1,3 +1,4 @@ +# This Python file uses the following encoding: utf-8 import re from django.conf import settings from django.utils.encoding import force_unicode @@ -36,15 +37,18 @@ return u''.join(_generator()) wrap = allow_lazy(wrap, unicode) -def truncate_words(s, num): +def truncate_words(s, num, add_ellipsis=True): "Truncates a string after a certain number of words." s = force_unicode(s) length = int(num) words = s.split() if len(words) > length: words = words[:length] - if not words[-1].endswith('...'): - words.append('...') + + if add_ellipsis: + if not words[-1].endswith(u'…'): + words.append(u'…') + return u' '.join(words) truncate_words = allow_lazy(truncate_words, unicode) =================================================================== --- defaultfilters.py (revision 7568) +++ defaultfilters.py (working copy) @@ -210,18 +210,24 @@ title.is_safe = True title = stringfilter(title) -def truncatewords(value, arg): +def truncatewords(value, arg, add_ellipsis=True): """ Truncates a string after a certain number of words. - Argument: Number of words to truncate after. + Argument: Number of words to truncate after. And, (optional) whether or not to add an ellipsis. """ from django.utils.text import truncate_words + try: length = int(arg) except ValueError: # Invalid literal for int(). return value # Fail silently. - return truncate_words(value, length) + + if length<0: + add_ellipsis = False; + length = abs(length) + + return truncate_words(value, length, add_ellipsis) truncatewords.is_safe = True truncatewords = stringfilter(truncatewords) }}} On Jun 4, 3:27 pm, Aral Balkan <[EMAIL PROTECTED]> wrote: > Hi Russell, > > Cool, thanks -- will post it as a ticket now. And apologies for the > messed up syntax in the previous post -- will clean it up for the > ticket. > > Aral <snip> --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@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-developers?hl=en -~----------~----~----~----~------~----~------~--~---