Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Fixed #1919 -- filter truncatewords is inefficient and destroys white space #1175

Open
wants to merge 6 commits into from

4 participants

Chris Wilson zhongqi Ramiro Morales Tim Graham
Chris Wilson
qris commented

Used @arien's patch and @SmileyChris' comments, integrated with current code, hopefully made even more efficient for long strings by not splitting and rejoining them.

https://code.djangoproject.com/ticket/1919

and others added some commits
zhongqi Update customizing.txt
The origin statement "which could be ... or whatever" **misguides** many newbies like me.

In fact, the ``login`` function in ``contrib.auth`` stores ``user.pk`` in session, then ``get_user`` function in ``contrib.auth`` gets ``user.pk`` in session and then passes it to your custom ``get_user`` as ``user_id``.

Which means, ``user_id`` prarameter in your custom ``get_user`` has to be the primary key of ``User`` object, too.
1172bef
Ramiro Morales Updated test failure example. 956973c
Tim Graham Merge pull request #1058 from svisser/ticket_20397
Fixed #20397 - Cleaned up issue with quotation marks in documentation
b1f7467
Tim Graham Fixed #20398 - Added language selection code to example in documentation
Thanks ggbaker for the suggestion and Simeon Visser for the patch.
897e4ea
Tim Graham Merge pull request #1053 from makto/patch-1
Fixed #20394 - Clarified argument of get_user in docs
1708c8a
Chris Wilson Fixed #1919 -- filter truncatewords destroys white space
Used @arien's patch and @SmileyChris' comments, integrated with current
code, hopefully made even more efficient for long strings by not
splitting and rejoining them.

https://code.djangoproject.com/ticket/1919
cfeaf42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 6 unique commits by 4 authors.

May 11, 2013
zhongqi Update customizing.txt
The origin statement "which could be ... or whatever" **misguides** many newbies like me.

In fact, the ``login`` function in ``contrib.auth`` stores ``user.pk`` in session, then ``get_user`` function in ``contrib.auth`` gets ``user.pk`` in session and then passes it to your custom ``get_user`` as ``user_id``.

Which means, ``user_id`` prarameter in your custom ``get_user`` has to be the primary key of ``User`` object, too.
1172bef
May 12, 2013
Ramiro Morales Updated test failure example. 956973c
Tim Graham Merge pull request #1058 from svisser/ticket_20397
Fixed #20397 - Cleaned up issue with quotation marks in documentation
b1f7467
May 13, 2013
Tim Graham Fixed #20398 - Added language selection code to example in documentation
Thanks ggbaker for the suggestion and Simeon Visser for the patch.
897e4ea
Tim Graham Merge pull request #1053 from makto/patch-1
Fixed #20394 - Clarified argument of get_user in docs
1708c8a
May 19, 2013
Chris Wilson Fixed #1919 -- filter truncatewords destroys white space
Used @arien's patch and @SmileyChris' comments, integrated with current
code, hopefully made even more efficient for long strings by not
splitting and rejoining them.

https://code.djangoproject.com/ticket/1919
cfeaf42
This page is out of date. Refresh to see the latest.
34  django/utils/text.py
@@ -79,6 +79,7 @@ def add_truncation_text(self, text, truncate=None):
79 79
             return text
80 80
         return '%s%s' % (text, truncate)
81 81
 
  82
+    @allow_lazy
82 83
     def chars(self, num, truncate=None):
83 84
         """
84 85
         Returns the text truncated to be no longer than the specified number
@@ -116,8 +117,8 @@ def chars(self, num, truncate=None):
116 117
 
117 118
         # Return the original string since no truncation was necessary
118 119
         return text
119  
-    chars = allow_lazy(chars)
120 120
 
  121
+    @allow_lazy
121 122
     def words(self, num, truncate=None, html=False):
122 123
         """
123 124
         Truncates a string after a certain number of words. Takes an optional
@@ -128,19 +129,34 @@ def words(self, num, truncate=None, html=False):
128 129
         if html:
129 130
             return self._html_words(length, truncate)
130 131
         return self._text_words(length, truncate)
131  
-    words = allow_lazy(words)
132 132
 
133  
-    def _text_words(self, length, truncate):
  133
+    word_re = re.compile(r'\S+')
  134
+
  135
+    def _text_words(self, max_words, ellipsis):
134 136
         """
135 137
         Truncates a string after a certain number of words.
136 138
 
137  
-        Newlines in the string will be stripped.
  139
+        Whitespace within the string will not be modified before the
  140
+        truncation point.
  141
+        maximum  is reached.
138 142
         """
139  
-        words = self._wrapped.split()
140  
-        if len(words) > length:
141  
-            words = words[:length]
142  
-            return self.add_truncation_text(' '.join(words), truncate)
143  
-        return ' '.join(words)
  143
+        if max_words < 1:
  144
+            return u''
  145
+
  146
+        word_count = 0
  147
+        truncation_point = None
  148
+
  149
+        for match in self.word_re.finditer(self._wrapped):
  150
+            word_count += 1
  151
+            if word_count == max_words:
  152
+                truncation_point = match.end() 
  153
+                break
  154
+
  155
+        if truncation_point is None:
  156
+            return self._wrapped
  157
+        else:
  158
+            return self.add_truncation_text(self._wrapped[:truncation_point],
  159
+                ellipsis)
144 160
 
145 161
     def _html_words(self, length, truncate):
146 162
         """
2  docs/index.txt
@@ -185,7 +185,7 @@ testing of Django applications:
185 185
 * **Testing:**
186 186
   :doc:`Introduction <topics/testing/index>` |
187 187
   :doc:`Writing and running tests <topics/testing/overview>` |
188  
-  :doc:`Advanced topics <topics/testing/advanced>` |
  188
+  :doc:`Advanced topics <topics/testing/advanced>`
189 189
 
190 190
 * **Deployment:**
191 191
   :doc:`Overview <howto/deployment/index>` |
3  docs/topics/auth/customizing.txt
@@ -95,7 +95,8 @@ An authentication backend is a class that implements two required methods:
95 95
 optional permission related :ref:`authorization methods <authorization_methods>`.
96 96
 
97 97
 The ``get_user`` method takes a ``user_id`` -- which could be a username,
98  
-database ID or whatever -- and returns a ``User`` object.
  98
+database ID or whatever, but has to be the primary key of your ``User`` object
  99
+-- and returns a ``User`` object.
99 100
 
100 101
 The ``authenticate`` method takes credentials as keyword arguments. Most of
101 102
 the time, it'll just look like this::
4  docs/topics/i18n/translation.txt
@@ -1437,7 +1437,9 @@ Here's example HTML template code:
1437 1437
     <select name="language">
1438 1438
     {% get_language_info_list for LANGUAGES as languages %}
1439 1439
     {% for language in languages %}
1440  
-    <option value="{{ language.code }}">{{ language.name_local }} ({{ language.code }})</option>
  1440
+    <option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}>
  1441
+        {{ language.name_local }} ({{ language.code }})
  1442
+    </option>
1441 1443
     {% endfor %}
1442 1444
     </select>
1443 1445
     <input type="submit" value="Go" />
20  docs/topics/testing/overview.txt
@@ -280,25 +280,15 @@ If there are test failures, however, you'll see full details about which tests
280 280
 failed::
281 281
 
282 282
     ======================================================================
283  
-    FAIL: Doctest: ellington.core.throttle.models
  283
+    FAIL: test_was_published_recently_with_future_poll (polls.tests.PollMethodTests)
284 284
     ----------------------------------------------------------------------
285 285
     Traceback (most recent call last):
286  
-      File "/dev/django/test/doctest.py", line 2153, in runTest
287  
-        raise self.failureException(self.format_failure(new.getvalue()))
288  
-    AssertionError: Failed doctest test for myapp.models
289  
-      File "/dev/myapp/models.py", line 0, in models
  286
+      File "/dev/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_poll
  287
+        self.assertEqual(future_poll.was_published_recently(), False)
  288
+    AssertionError: True != False
290 289
 
291 290
     ----------------------------------------------------------------------
292  
-    File "/dev/myapp/models.py", line 14, in myapp.models
293  
-    Failed example:
294  
-        throttle.check("actor A", "action one", limit=2, hours=1)
295  
-    Expected:
296  
-        True
297  
-    Got:
298  
-        False
299  
-
300  
-    ----------------------------------------------------------------------
301  
-    Ran 2 tests in 0.048s
  291
+    Ran 1 test in 0.003s
302 292
 
303 293
     FAILED (failures=1)
304 294
 
18  tests/defaultfilters/tests.py
@@ -163,7 +163,23 @@ def test_truncatewords(self):
163 163
         self.assertEqual(
164 164
             truncatewords('A sentence with a few words in it',
165 165
             'not a number'), 'A sentence with a few words in it')
166  
-
  166
+        self.assertEqual(
  167
+            truncatewords('Double-spaced  sentence  with  a  few  words', 2),
  168
+            'Double-spaced  sentence ...')
  169
+        self.assertEqual(
  170
+            truncatewords('  Two leading spaces for this sentence', 3),
  171
+            '  Two leading spaces ...')
  172
+        self.assertEqual(
  173
+            truncatewords('  Text with leading and trailing whitespace  ', 10),
  174
+            '  Text with leading and trailing whitespace  ')
  175
+        self.assertEqual(
  176
+            truncatewords('  Text with leading and trailing whitespace  ', 6),
  177
+            '  Text with leading and trailing whitespace ...')
  178
+        self.assertEqual(
  179
+            truncatewords('  Text with leading and trailing whitespace  ', 1),
  180
+            '  Text ...')
  181
+        self.assertEqual(truncatewords('  Text  ', 0), '')
  182
+        
167 183
     def test_truncatewords_html(self):
168 184
         self.assertEqual(truncatewords_html(
169 185
             '<p>one <a href="#">two - three <br>four</a> five</p>', 0), '')
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.