Use stdlib html.escape() in django.utils.html.escape()

Improves performance and removes duplicated code by leveraging Python's built-in html.escape(). Note: changes escaping of single quotes from ' to ', which may affect literal output.
This commit is contained in:
utkarsh.arya@zomato.com 2025-11-15 22:56:59 +00:00
parent 28d5262fa3
commit 7fcafcc265
14 changed files with 36 additions and 44 deletions

View file

@ -1,5 +1,6 @@
"""HTML utilities suitable for global use.""" """HTML utilities suitable for global use."""
import html
import json import json
import re import re
from html.parser import HTMLParser from html.parser import HTMLParser
@ -24,15 +25,6 @@ word_split_re = re.compile(r'''([\s<>"']+)''')
simple_url_re = re.compile(r'^https?://\[?\w', re.IGNORECASE) simple_url_re = re.compile(r'^https?://\[?\w', re.IGNORECASE)
simple_url_2_re = re.compile(r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)($|/.*)$', re.IGNORECASE) simple_url_2_re = re.compile(r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)($|/.*)$', re.IGNORECASE)
_html_escapes = {
ord('&'): '&amp;',
ord('<'): '&lt;',
ord('>'): '&gt;',
ord('"'): '&quot;',
ord("'"): '&#39;',
}
@keep_lazy(str, SafeString) @keep_lazy(str, SafeString)
def escape(text): def escape(text):
""" """
@ -43,7 +35,7 @@ def escape(text):
This may result in double-escaping. If this is a concern, use This may result in double-escaping. If this is a concern, use
conditional_escape() instead. conditional_escape() instead.
""" """
return mark_safe(str(text).translate(_html_escapes)) return mark_safe(html.escape(str(text)))
_js_escapes = { _js_escapes = {
@ -266,7 +258,7 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
http://example.com?x=1&amp;y=&lt;2&gt; => http://example.com?x=1&y=<2> http://example.com?x=1&amp;y=&lt;2&gt; => http://example.com?x=1&y=<2>
""" """
return text.replace('&amp;', '&').replace('&lt;', '<').replace( return text.replace('&amp;', '&').replace('&lt;', '<').replace(
'&gt;', '>').replace('&quot;', '"').replace('&#39;', "'") '&gt;', '>').replace('&quot;', '"').replace('&#x27;', "'").replace('&#39;', "'")
def trim_punctuation(lead, middle, trail): def trim_punctuation(lead, middle, trail):
""" """

View file

@ -199,7 +199,7 @@ class TestModelDetailView(TestDataMixin, AdminDocsTestCase):
""" """
Methods with keyword arguments should have their arguments displayed. Methods with keyword arguments should have their arguments displayed.
""" """
self.assertContains(self.response, "<td>suffix=&#39;ltd&#39;</td>") self.assertContains(self.response, "<td>suffix=&#x27;ltd&#x27;</td>")
def test_methods_with_multiple_arguments_display_arguments(self): def test_methods_with_multiple_arguments_display_arguments(self):
""" """

View file

@ -236,7 +236,7 @@ class UserCreationFormTest(TestDataMixin, TestCase):
form = UserCreationForm() form = UserCreationForm()
self.assertEqual( self.assertEqual(
form.fields['password1'].help_text, form.fields['password1'].help_text,
'<ul><li>Your password can&#39;t be too similar to your other personal information.</li></ul>' '<ul><li>Your password can&#x27;t be too similar to your other personal information.</li></ul>'
) )
@override_settings(AUTH_PASSWORD_VALIDATORS=[ @override_settings(AUTH_PASSWORD_VALIDATORS=[

View file

@ -995,7 +995,7 @@ Java</label></li>
self.assertHTMLEqual( self.assertHTMLEqual(
f.as_table(), f.as_table(),
"""<tr><th>&lt;em&gt;Special&lt;/em&gt; Field:</th><td> """<tr><th>&lt;em&gt;Special&lt;/em&gt; Field:</th><td>
<ul class="errorlist"><li>Something&#39;s wrong with &#39;Nothing to escape&#39;</li></ul> <ul class="errorlist"><li>Something&#x27;s wrong with &#x27;Nothing to escape&#x27;</li></ul>
<input type="text" name="special_name" value="Nothing to escape" required></td></tr> <input type="text" name="special_name" value="Nothing to escape" required></td></tr>
<tr><th><em>Special</em> Field:</th><td> <tr><th><em>Special</em> Field:</th><td>
<ul class="errorlist"><li>'<b>Nothing to escape</b>' is a safe string</li></ul> <ul class="errorlist"><li>'<b>Nothing to escape</b>' is a safe string</li></ul>
@ -1008,10 +1008,10 @@ Java</label></li>
self.assertHTMLEqual( self.assertHTMLEqual(
f.as_table(), f.as_table(),
"""<tr><th>&lt;em&gt;Special&lt;/em&gt; Field:</th><td> """<tr><th>&lt;em&gt;Special&lt;/em&gt; Field:</th><td>
<ul class="errorlist"><li>Something&#39;s wrong with &#39;Should escape &lt; &amp; &gt; and <ul class="errorlist"><li>Something&#x27;s wrong with &#x27;Should escape &lt; &amp; &gt; and
&lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;&#39;</li></ul> &lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;&#x27;</li></ul>
<input type="text" name="special_name" <input type="text" name="special_name"
value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;" required></td></tr> value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;" required></td></tr>
<tr><th><em>Special</em> Field:</th><td> <tr><th><em>Special</em> Field:</th><td>
<ul class="errorlist"><li>'<b><i>Do not escape</i></b>' is a safe string</li></ul> <ul class="errorlist"><li>'<b><i>Do not escape</i></b>' is a safe string</li></ul>
<input type="text" name="special_safe_name" value="&lt;i&gt;Do not escape&lt;/i&gt;" required></td></tr>""" <input type="text" name="special_safe_name" value="&lt;i&gt;Do not escape&lt;/i&gt;" required></td></tr>"""
@ -2632,7 +2632,7 @@ Password: <input type="password" name="password" required>
t.render(Context({'form': UserRegistration(auto_id=False)})), t.render(Context({'form': UserRegistration(auto_id=False)})),
"""<form> """<form>
<p>Username: <input type="text" name="username" maxlength="10" required><br> <p>Username: <input type="text" name="username" maxlength="10" required><br>
Good luck picking a username that doesn&#39;t already exist.</p> Good luck picking a username that doesn&#x27;t already exist.</p>
<p>Password1: <input type="password" name="password1" required></p> <p>Password1: <input type="password" name="password1" required></p>
<p>Password2: <input type="password" name="password2" required></p> <p>Password2: <input type="password" name="password2" required></p>
<input type="submit" required> <input type="submit" required>

View file

@ -46,7 +46,7 @@ class ClearableFileInputTest(WidgetTest):
self.check_html(ClearableFileInput(), 'my<div>file', StrangeFieldFile(), html=( self.check_html(ClearableFileInput(), 'my<div>file', StrangeFieldFile(), html=(
""" """
Currently: <a href="something?chapter=1&amp;sect=2&amp;copy=3&amp;lang=en"> Currently: <a href="something?chapter=1&amp;sect=2&amp;copy=3&amp;lang=en">
something&lt;div onclick=&quot;alert(&#39;oops&#39;)&quot;&gt;.jpg</a> something&lt;div onclick=&quot;alert(&#x27;oops&#x27;)&quot;&gt;.jpg</a>
<input type="checkbox" name="my&lt;div&gt;file-clear" id="my&lt;div&gt;file-clear_id"> <input type="checkbox" name="my&lt;div&gt;file-clear" id="my&lt;div&gt;file-clear_id">
<label for="my&lt;div&gt;file-clear_id">Clear</label><br> <label for="my&lt;div&gt;file-clear_id">Clear</label><br>
Change: <input type="file" name="my&lt;div&gt;file"> Change: <input type="file" name="my&lt;div&gt;file">

View file

@ -1197,7 +1197,7 @@ class ModelFormBasicTests(TestCase):
<li>Article: <textarea rows="10" cols="40" name="article" required></textarea></li> <li>Article: <textarea rows="10" cols="40" name="article" required></textarea></li>
<li>Categories: <select multiple name="categories"> <li>Categories: <select multiple name="categories">
<option value="%s" selected>Entertainment</option> <option value="%s" selected>Entertainment</option>
<option value="%s" selected>It&#39;s a test</option> <option value="%s" selected>It&#x27;s a test</option>
<option value="%s">Third test</option> <option value="%s">Third test</option>
</select></li> </select></li>
<li>Status: <select name="status"> <li>Status: <select name="status">
@ -1239,7 +1239,7 @@ class ModelFormBasicTests(TestCase):
<li>Article: <textarea rows="10" cols="40" name="article" required>Hello.</textarea></li> <li>Article: <textarea rows="10" cols="40" name="article" required>Hello.</textarea></li>
<li>Categories: <select multiple name="categories"> <li>Categories: <select multiple name="categories">
<option value="%s">Entertainment</option> <option value="%s">Entertainment</option>
<option value="%s">It&#39;s a test</option> <option value="%s">It&#x27;s a test</option>
<option value="%s">Third test</option> <option value="%s">Third test</option>
</select></li> </select></li>
<li>Status: <select name="status"> <li>Status: <select name="status">
@ -1361,7 +1361,7 @@ class ModelFormBasicTests(TestCase):
<tr><th>Article:</th><td><textarea rows="10" cols="40" name="article" required></textarea></td></tr> <tr><th>Article:</th><td><textarea rows="10" cols="40" name="article" required></textarea></td></tr>
<tr><th>Categories:</th><td><select multiple name="categories"> <tr><th>Categories:</th><td><select multiple name="categories">
<option value="%s">Entertainment</option> <option value="%s">Entertainment</option>
<option value="%s">It&#39;s a test</option> <option value="%s">It&#x27;s a test</option>
<option value="%s">Third test</option> <option value="%s">Third test</option>
</select></td></tr> </select></td></tr>
<tr><th>Status:</th><td><select name="status"> <tr><th>Status:</th><td><select name="status">
@ -1391,7 +1391,7 @@ class ModelFormBasicTests(TestCase):
<li>Article: <textarea rows="10" cols="40" name="article" required>Hello.</textarea></li> <li>Article: <textarea rows="10" cols="40" name="article" required>Hello.</textarea></li>
<li>Categories: <select multiple name="categories"> <li>Categories: <select multiple name="categories">
<option value="%s" selected>Entertainment</option> <option value="%s" selected>Entertainment</option>
<option value="%s">It&#39;s a test</option> <option value="%s">It&#x27;s a test</option>
<option value="%s">Third test</option> <option value="%s">Third test</option>
</select></li> </select></li>
<li>Status: <select name="status"> <li>Status: <select name="status">
@ -1535,7 +1535,7 @@ class ModelFormBasicTests(TestCase):
<li>Article: <textarea rows="10" cols="40" name="article" required></textarea></li> <li>Article: <textarea rows="10" cols="40" name="article" required></textarea></li>
<li>Categories: <select multiple name="categories"> <li>Categories: <select multiple name="categories">
<option value="%s">Entertainment</option> <option value="%s">Entertainment</option>
<option value="%s">It&#39;s a test</option> <option value="%s">It&#x27;s a test</option>
<option value="%s">Third test</option> <option value="%s">Third test</option>
</select> </li> </select> </li>
<li>Status: <select name="status"> <li>Status: <select name="status">
@ -1561,7 +1561,7 @@ class ModelFormBasicTests(TestCase):
<li>Article: <textarea rows="10" cols="40" name="article" required></textarea></li> <li>Article: <textarea rows="10" cols="40" name="article" required></textarea></li>
<li>Categories: <select multiple name="categories"> <li>Categories: <select multiple name="categories">
<option value="%s">Entertainment</option> <option value="%s">Entertainment</option>
<option value="%s">It&#39;s a test</option> <option value="%s">It&#x27;s a test</option>
<option value="%s">Third test</option> <option value="%s">Third test</option>
<option value="%s">Fourth</option> <option value="%s">Fourth</option>
</select></li> </select></li>

View file

@ -15,7 +15,7 @@ class AddslashesTests(SimpleTestCase):
@setup({'addslashes02': '{{ a|addslashes }} {{ b|addslashes }}'}) @setup({'addslashes02': '{{ a|addslashes }} {{ b|addslashes }}'})
def test_addslashes02(self): def test_addslashes02(self):
output = self.engine.render_to_string('addslashes02', {"a": "<a>'", "b": mark_safe("<a>'")}) output = self.engine.render_to_string('addslashes02', {"a": "<a>'", "b": mark_safe("<a>'")})
self.assertEqual(output, r"&lt;a&gt;\&#39; <a>\'") self.assertEqual(output, r"&lt;a&gt;\&#x27; <a>\'")
class FunctionTests(SimpleTestCase): class FunctionTests(SimpleTestCase):

View file

@ -19,7 +19,7 @@ class MakeListTests(SimpleTestCase):
@setup({'make_list02': '{{ a|make_list }}'}) @setup({'make_list02': '{{ a|make_list }}'})
def test_make_list02(self): def test_make_list02(self):
output = self.engine.render_to_string('make_list02', {"a": mark_safe("&")}) output = self.engine.render_to_string('make_list02', {"a": mark_safe("&")})
self.assertEqual(output, "[&#39;&amp;&#39;]") self.assertEqual(output, "[&#x27;&amp;&#x27;]")
@setup({'make_list03': '{% autoescape off %}{{ a|make_list|stringformat:"s"|safe }}{% endautoescape %}'}) @setup({'make_list03': '{% autoescape off %}{{ a|make_list|stringformat:"s"|safe }}{% endautoescape %}'})
def test_make_list03(self): def test_make_list03(self):

View file

@ -9,7 +9,7 @@ class TitleTests(SimpleTestCase):
@setup({'title1': '{{ a|title }}'}) @setup({'title1': '{{ a|title }}'})
def test_title1(self): def test_title1(self):
output = self.engine.render_to_string('title1', {'a': 'JOE\'S CRAB SHACK'}) output = self.engine.render_to_string('title1', {'a': 'JOE\'S CRAB SHACK'})
self.assertEqual(output, 'Joe&#39;s Crab Shack') self.assertEqual(output, 'Joe&#x27;s Crab Shack')
@setup({'title2': '{{ a|title }}'}) @setup({'title2': '{{ a|title }}'})
def test_title2(self): def test_title2(self):

View file

@ -52,7 +52,7 @@ class UrlizeTests(SimpleTestCase):
@setup({'urlize06': '{{ a|urlize }}'}) @setup({'urlize06': '{{ a|urlize }}'})
def test_urlize06(self): def test_urlize06(self):
output = self.engine.render_to_string('urlize06', {'a': "<script>alert('foo')</script>"}) output = self.engine.render_to_string('urlize06', {'a': "<script>alert('foo')</script>"})
self.assertEqual(output, '&lt;script&gt;alert(&#39;foo&#39;)&lt;/script&gt;') self.assertEqual(output, '&lt;script&gt;alert(&#x27;foo&#x27;)&lt;/script&gt;')
# mailto: testing for urlize # mailto: testing for urlize
@setup({'urlize07': '{{ a|urlize }}'}) @setup({'urlize07': '{{ a|urlize }}'})
@ -113,7 +113,7 @@ class FunctionTests(SimpleTestCase):
) )
self.assertEqual( self.assertEqual(
urlize('www.server.com\'abc'), urlize('www.server.com\'abc'),
'<a href="http://www.server.com" rel="nofollow">www.server.com</a>&#39;abc', '<a href="http://www.server.com" rel="nofollow">www.server.com</a>&#x27;abc',
) )
self.assertEqual( self.assertEqual(
urlize('www.server.com<abc'), urlize('www.server.com<abc'),
@ -284,7 +284,7 @@ class FunctionTests(SimpleTestCase):
('<>', ('&lt;', '&gt;')), ('<>', ('&lt;', '&gt;')),
('[]', ('[', ']')), ('[]', ('[', ']')),
('""', ('&quot;', '&quot;')), ('""', ('&quot;', '&quot;')),
("''", ('&#39;', '&#39;')), ("''", ('&#x27;', '&#x27;')),
) )
for wrapping_in, (start_out, end_out) in wrapping_chars: for wrapping_in, (start_out, end_out) in wrapping_chars:
with self.subTest(wrapping_in=wrapping_in): with self.subTest(wrapping_in=wrapping_in):

View file

@ -78,7 +78,7 @@ class UrlTagTests(SimpleTestCase):
@setup({'url12': '{% url "client_action" id=client.id action="!$&\'()*+,;=~:@," %}'}) @setup({'url12': '{% url "client_action" id=client.id action="!$&\'()*+,;=~:@," %}'})
def test_url12(self): def test_url12(self):
output = self.engine.render_to_string('url12', {'client': {'id': 1}}) output = self.engine.render_to_string('url12', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/!$&amp;&#39;()*+,;=~:@,/') self.assertEqual(output, '/client/1/!$&amp;&#x27;()*+,;=~:@,/')
@setup({'url13': '{% url "client_action" id=client.id action=arg|join:"-" %}'}) @setup({'url13': '{% url "client_action" id=client.id action=arg|join:"-" %}'})
def test_url13(self): def test_url13(self):

View file

@ -27,7 +27,7 @@ class TestUtilsHtml(SimpleTestCase):
('<', '&lt;'), ('<', '&lt;'),
('>', '&gt;'), ('>', '&gt;'),
('"', '&quot;'), ('"', '&quot;'),
("'", '&#39;'), ("'", '&#x27;'),
) )
# Substitution patterns for testing the above items. # Substitution patterns for testing the above items.
patterns = ("%s", "asdf%sfdsa", "%s1", "1%sb") patterns = ("%s", "asdf%sfdsa", "%s1", "1%sb")

View file

@ -44,22 +44,22 @@ class CsrfViewTests(SimpleTestCase):
self.assertContains( self.assertContains(
response, response,
'You are seeing this message because this HTTPS site requires a ' 'You are seeing this message because this HTTPS site requires a '
'&#39;Referer header&#39; to be sent by your Web browser, but ' '&#x27;Referer header&#x27; to be sent by your Web browser, but '
'none was sent.', 'none was sent.',
status_code=403, status_code=403,
) )
self.assertContains( self.assertContains(
response, response,
'If you have configured your browser to disable &#39;Referer&#39; ' 'If you have configured your browser to disable &#x27;Referer&#x27; '
'headers, please re-enable them, at least for this site, or for ' 'headers, please re-enable them, at least for this site, or for '
'HTTPS connections, or for &#39;same-origin&#39; requests.', 'HTTPS connections, or for &#x27;same-origin&#x27; requests.',
status_code=403, status_code=403,
) )
self.assertContains( self.assertContains(
response, response,
'If you are using the &lt;meta name=&quot;referrer&quot; ' 'If you are using the &lt;meta name=&quot;referrer&quot; '
'content=&quot;no-referrer&quot;&gt; tag or including the ' 'content=&quot;no-referrer&quot;&gt; tag or including the '
'&#39;Referrer-Policy: no-referrer&#39; header, please remove them.', '&#x27;Referrer-Policy: no-referrer&#x27; header, please remove them.',
status_code=403, status_code=403,
) )

View file

@ -304,7 +304,7 @@ class ExceptionReporterTests(SimpleTestCase):
reporter = ExceptionReporter(request, exc_type, exc_value, tb) reporter = ExceptionReporter(request, exc_type, exc_value, tb)
html = reporter.get_traceback_html() html = reporter.get_traceback_html()
self.assertInHTML('<h1>ValueError at /test_view/</h1>', html) self.assertInHTML('<h1>ValueError at /test_view/</h1>', html)
self.assertIn('<pre class="exception_value">Can&#39;t find my keys</pre>', html) self.assertIn('<pre class="exception_value">Can&#x27;t find my keys</pre>', html)
self.assertIn('<th>Request Method:</th>', html) self.assertIn('<th>Request Method:</th>', html)
self.assertIn('<th>Request URL:</th>', html) self.assertIn('<th>Request URL:</th>', html)
self.assertIn('<h3 id="user-info">USER</h3>', html) self.assertIn('<h3 id="user-info">USER</h3>', html)
@ -325,7 +325,7 @@ class ExceptionReporterTests(SimpleTestCase):
reporter = ExceptionReporter(None, exc_type, exc_value, tb) reporter = ExceptionReporter(None, exc_type, exc_value, tb)
html = reporter.get_traceback_html() html = reporter.get_traceback_html()
self.assertInHTML('<h1>ValueError</h1>', html) self.assertInHTML('<h1>ValueError</h1>', html)
self.assertIn('<pre class="exception_value">Can&#39;t find my keys</pre>', html) self.assertIn('<pre class="exception_value">Can&#x27;t find my keys</pre>', html)
self.assertNotIn('<th>Request Method:</th>', html) self.assertNotIn('<th>Request Method:</th>', html)
self.assertNotIn('<th>Request URL:</th>', html) self.assertNotIn('<th>Request URL:</th>', html)
self.assertNotIn('<h3 id="user-info">USER</h3>', html) self.assertNotIn('<h3 id="user-info">USER</h3>', html)
@ -463,7 +463,7 @@ class ExceptionReporterTests(SimpleTestCase):
reporter = ExceptionReporter(request, None, "I'm a little teapot", None) reporter = ExceptionReporter(request, None, "I'm a little teapot", None)
html = reporter.get_traceback_html() html = reporter.get_traceback_html()
self.assertInHTML('<h1>Report at /test_view/</h1>', html) self.assertInHTML('<h1>Report at /test_view/</h1>', html)
self.assertIn('<pre class="exception_value">I&#39;m a little teapot</pre>', html) self.assertIn('<pre class="exception_value">I&#x27;m a little teapot</pre>', html)
self.assertIn('<th>Request Method:</th>', html) self.assertIn('<th>Request Method:</th>', html)
self.assertIn('<th>Request URL:</th>', html) self.assertIn('<th>Request URL:</th>', html)
self.assertNotIn('<th>Exception Type:</th>', html) self.assertNotIn('<th>Exception Type:</th>', html)
@ -476,7 +476,7 @@ class ExceptionReporterTests(SimpleTestCase):
reporter = ExceptionReporter(None, None, "I'm a little teapot", None) reporter = ExceptionReporter(None, None, "I'm a little teapot", None)
html = reporter.get_traceback_html() html = reporter.get_traceback_html()
self.assertInHTML('<h1>Report</h1>', html) self.assertInHTML('<h1>Report</h1>', html)
self.assertIn('<pre class="exception_value">I&#39;m a little teapot</pre>', html) self.assertIn('<pre class="exception_value">I&#x27;m a little teapot</pre>', html)
self.assertNotIn('<th>Request Method:</th>', html) self.assertNotIn('<th>Request Method:</th>', html)
self.assertNotIn('<th>Request URL:</th>', html) self.assertNotIn('<th>Request URL:</th>', html)
self.assertNotIn('<th>Exception Type:</th>', html) self.assertNotIn('<th>Exception Type:</th>', html)
@ -508,7 +508,7 @@ class ExceptionReporterTests(SimpleTestCase):
except Exception: except Exception:
exc_type, exc_value, tb = sys.exc_info() exc_type, exc_value, tb = sys.exc_info()
html = ExceptionReporter(None, exc_type, exc_value, tb).get_traceback_html() html = ExceptionReporter(None, exc_type, exc_value, tb).get_traceback_html()
self.assertIn('<td class="code"><pre>&#39;&lt;p&gt;Local variable&lt;/p&gt;&#39;</pre></td>', html) self.assertIn('<td class="code"><pre>&#x27;&lt;p&gt;Local variable&lt;/p&gt;&#x27;</pre></td>', html)
def test_unprintable_values_handling(self): def test_unprintable_values_handling(self):
"Unprintable values should not make the output generation choke." "Unprintable values should not make the output generation choke."
@ -607,7 +607,7 @@ class ExceptionReporterTests(SimpleTestCase):
An exception report can be generated for requests with 'items' in An exception report can be generated for requests with 'items' in
request GET, POST, FILES, or COOKIES QueryDicts. request GET, POST, FILES, or COOKIES QueryDicts.
""" """
value = '<td>items</td><td class="code"><pre>&#39;Oops&#39;</pre></td>' value = '<td>items</td><td class="code"><pre>&#x27;Oops&#x27;</pre></td>'
# GET # GET
request = self.rf.get('/test_view/?items=Oops') request = self.rf.get('/test_view/?items=Oops')
reporter = ExceptionReporter(request, None, None, None) reporter = ExceptionReporter(request, None, None, None)
@ -634,7 +634,7 @@ class ExceptionReporterTests(SimpleTestCase):
request = rf.get('/test_view/') request = rf.get('/test_view/')
reporter = ExceptionReporter(request, None, None, None) reporter = ExceptionReporter(request, None, None, None)
html = reporter.get_traceback_html() html = reporter.get_traceback_html()
self.assertInHTML('<td>items</td><td class="code"><pre>&#39;Oops&#39;</pre></td>', html) self.assertInHTML('<td>items</td><td class="code"><pre>&#x27;Oops&#x27;</pre></td>', html)
def test_exception_fetching_user(self): def test_exception_fetching_user(self):
""" """