diff options
| author | Claude Paroz <claude@2xlibre.net> | 2015-12-12 23:09:13 +0100 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2015-12-13 15:07:17 +0100 |
| commit | ed20dd2e85a0bbd45085809417c29e92ced5e618 (patch) | |
| tree | 370cfa35c35ccc1be5be57ab2d657915853403a0 | |
| parent | d693074d431c50e4801dd6bf52525ce1436358f0 (diff) | |
Fixed #25875 -- Prevented UnicodeDecodeError for Q object repr
Thanks Ben Kraft for the report, and Simon Charette for the review.
| -rw-r--r-- | django/utils/tree.py | 11 | ||||
| -rw-r--r-- | tests/or_lookups/tests.py | 8 |
2 files changed, 13 insertions, 6 deletions
diff --git a/django/utils/tree.py b/django/utils/tree.py index 9eb3aeb5d6..50712bb866 100644 --- a/django/utils/tree.py +++ b/django/utils/tree.py @@ -5,6 +5,8 @@ ORM. import copy +from django.utils.encoding import force_str, force_text + class Node(object): """ @@ -42,14 +44,11 @@ class Node(object): return obj def __str__(self): - if self.negated: - return '(NOT (%s: %s))' % (self.connector, ', '.join(str(c) for c - in self.children)) - return '(%s: %s)' % (self.connector, ', '.join(str(c) for c in - self.children)) + template = '(NOT (%s: %s))' if self.negated else '(%s: %s)' + return force_str(template % (self.connector, ', '.join(force_text(c) for c in self.children))) def __repr__(self): - return "<%s: %s>" % (self.__class__.__name__, self) + return str("<%s: %s>") % (self.__class__.__name__, self) def __deepcopy__(self, memodict): """ diff --git a/tests/or_lookups/tests.py b/tests/or_lookups/tests.py index 55afed3fc4..35c7f34d61 100644 --- a/tests/or_lookups/tests.py +++ b/tests/or_lookups/tests.py @@ -1,3 +1,4 @@ +# -*- encoding: utf-8 -*- from __future__ import unicode_literals from datetime import datetime @@ -5,6 +6,7 @@ from operator import attrgetter from django.db.models import Q from django.test import TestCase +from django.utils.encoding import force_str from .models import Article @@ -123,6 +125,12 @@ class OrLookupsTests(TestCase): attrgetter("headline"), ) + def test_q_repr(self): + or_expr = Q(baz=Article(headline="Foö")) + self.assertEqual(repr(or_expr), force_str("<Q: (AND: ('baz', <Article: Foö>))>")) + negated_or = ~Q(baz=Article(headline="Foö")) + self.assertEqual(repr(negated_or), force_str("<Q: (NOT (AND: ('baz', <Article: Foö>)))>")) + def test_q_negated(self): # Q objects can be negated self.assertQuerysetEqual( |
