1 from __future__
import absolute_import
3 from datetime
import datetime
5 from django
.conf
import settings
6 from django
.contrib
import admin
7 from django
.contrib
.admin
import helpers
8 from django
.contrib
.admin
.util
import (display_for_field
, label_for_field
,
9 lookup_field
, NestedObjects
)
10 from django
.contrib
.admin
.views
.main
import EMPTY_CHANGELIST_VALUE
11 from django
.contrib
.sites
.models
import Site
12 from django
.db
import models
, DEFAULT_DB_ALIAS
13 from django
import forms
14 from django
.test
import TestCase
15 from django
.utils
import unittest
16 from django
.utils
.formats
import localize
17 from django
.utils
.safestring
import mark_safe
19 from .models
import Article
, Count
, Event
, Location
22 class NestedObjectsTests(TestCase
):
24 Tests for ``NestedObject`` utility collection.
28 self
.n
= NestedObjects(using
=DEFAULT_DB_ALIAS
)
29 self
.objs
= [Count
.objects
.create(num
=i
) for i
in range(5)]
31 def _check(self
, target
):
32 self
.assertEqual(self
.n
.nested(lambda obj
: obj
.num
), target
)
34 def _connect(self
, i
, j
):
35 self
.objs
[i
].parent
= self
.objs
[j
]
38 def _collect(self
, *indices
):
39 self
.n
.collect([self
.objs
[i
] for i
in indices
])
41 def test_unrelated_roots(self
):
45 self
._check
([0, 1, [2]])
47 def test_siblings(self
):
51 self
._check
([0, [1, 2]])
53 def test_non_added_parent(self
):
58 def test_cyclic(self
):
63 self
._check
([0, [1, [2]]])
65 def test_queries(self
):
68 # 1 query to fetch all children of 0 (1 and 2)
69 # 1 query to fetch all children of 1 and 2 (none)
70 # Should not require additional queries to populate the nested graph.
71 self
.assertNumQueries(2, self
._collect
, 0)
73 class UtilTests(unittest
.TestCase
):
74 def test_values_from_lookup_field(self
):
76 Regression test for #12654: lookup_field
78 SITE_NAME
= 'example.com'
79 TITLE_TEXT
= 'Some title'
80 CREATED_DATE
= datetime
.min
81 ADMIN_METHOD
= 'admin method'
82 SIMPLE_FUNCTION
= 'function'
83 INSTANCE_ATTRIBUTE
= 'attr'
85 class MockModelAdmin(object):
86 def get_admin_value(self
, obj
):
89 simple_function
= lambda obj
: SIMPLE_FUNCTION
92 site
=Site(domain
=SITE_NAME
),
96 article
.non_field
= INSTANCE_ATTRIBUTE
100 ('created', localize(CREATED_DATE
)),
101 ('title', TITLE_TEXT
),
102 ('get_admin_value', ADMIN_METHOD
),
103 (simple_function
, SIMPLE_FUNCTION
),
104 ('test_from_model', article
.test_from_model()),
105 ('non_field', INSTANCE_ATTRIBUTE
)
108 mock_admin
= MockModelAdmin()
109 for name
, value
in verifications
:
110 field
, attr
, resolved_value
= lookup_field(name
, article
, mock_admin
)
112 if field
is not None:
113 resolved_value
= display_for_field(resolved_value
, field
)
115 self
.assertEqual(value
, resolved_value
)
117 def test_null_display_for_field(self
):
119 Regression test for #12550: display_for_field should handle None
122 display_value
= display_for_field(None, models
.CharField())
123 self
.assertEqual(display_value
, EMPTY_CHANGELIST_VALUE
)
125 display_value
= display_for_field(None, models
.CharField(
130 self
.assertEqual(display_value
, "test_none")
132 display_value
= display_for_field(None, models
.DateField())
133 self
.assertEqual(display_value
, EMPTY_CHANGELIST_VALUE
)
135 display_value
= display_for_field(None, models
.TimeField())
136 self
.assertEqual(display_value
, EMPTY_CHANGELIST_VALUE
)
138 # Regression test for #13071: NullBooleanField has special
140 display_value
= display_for_field(None, models
.NullBooleanField())
141 expected
= u
'<img src="%sadmin/img/icon-unknown.gif" alt="None" />' % settings
.STATIC_URL
142 self
.assertEqual(display_value
, expected
)
144 display_value
= display_for_field(None, models
.DecimalField())
145 self
.assertEqual(display_value
, EMPTY_CHANGELIST_VALUE
)
147 display_value
= display_for_field(None, models
.FloatField())
148 self
.assertEqual(display_value
, EMPTY_CHANGELIST_VALUE
)
150 def test_label_for_field(self
):
152 Tests for label_for_field
155 label_for_field("title", Article
),
159 label_for_field("title2", Article
),
163 label_for_field("title2", Article
, return_attr
=True),
164 ("another name", None)
168 label_for_field("__unicode__", Article
),
172 label_for_field("__str__", Article
),
178 lambda: label_for_field("unknown", Article
)
181 def test_callable(obj
):
184 label_for_field(test_callable
, Article
),
188 label_for_field(test_callable
, Article
, return_attr
=True),
189 ("Test callable", test_callable
)
193 label_for_field("test_from_model", Article
),
197 label_for_field("test_from_model", Article
, return_attr
=True),
198 ("Test from model", Article
.test_from_model
)
201 label_for_field("test_from_model_with_override", Article
),
202 "not What you Expect"
206 label_for_field(lambda x
: "nothing", Article
),
210 class MockModelAdmin(object):
211 def test_from_model(self
, obj
):
213 test_from_model
.short_description
= "not Really the Model"
216 label_for_field("test_from_model", Article
, model_admin
=MockModelAdmin
),
217 "not Really the Model"
220 label_for_field("test_from_model", Article
,
221 model_admin
= MockModelAdmin
,
224 ("not Really the Model", MockModelAdmin
.test_from_model
)
227 def test_related_name(self
):
229 Regression test for #13963
232 label_for_field('location', Event
, return_attr
=True),
236 label_for_field('event', Location
, return_attr
=True),
237 ('awesome event', None),
240 label_for_field('guest', Event
, return_attr
=True),
241 ('awesome guest', None),
244 def test_logentry_unicode(self
):
246 Regression test for #15661
248 log_entry
= admin
.models
.LogEntry()
250 log_entry
.action_flag
= admin
.models
.ADDITION
252 unicode(log_entry
).startswith('Added ')
255 log_entry
.action_flag
= admin
.models
.CHANGE
257 unicode(log_entry
).startswith('Changed ')
260 log_entry
.action_flag
= admin
.models
.DELETION
262 unicode(log_entry
).startswith('Deleted ')
265 def test_safestring_in_field_label(self
):
266 # safestring should not be escaped
267 class MyForm(forms
.Form
):
268 text
= forms
.CharField(label
=mark_safe('<i>text</i>'))
269 cb
= forms
.BooleanField(label
=mark_safe('<i>cb</i>'))
272 self
.assertEqual(helpers
.AdminField(form
, 'text', is_first
=False).label_tag(),
273 '<label for="id_text" class="required inline"><i>text</i>:</label>')
274 self
.assertEqual(helpers
.AdminField(form
, 'cb', is_first
=False).label_tag(),
275 '<label for="id_cb" class="vCheckboxLabel required inline"><i>cb</i></label>')
277 # normal strings needs to be escaped
278 class MyForm(forms
.Form
):
279 text
= forms
.CharField(label
='&text')
280 cb
= forms
.BooleanField(label
='&cb')
283 self
.assertEqual(helpers
.AdminField(form
, 'text', is_first
=False).label_tag(),
284 '<label for="id_text" class="required inline">&text:</label>')
285 self
.assertEqual(helpers
.AdminField(form
, 'cb', is_first
=False).label_tag(),
286 '<label for="id_cb" class="vCheckboxLabel required inline">&cb</label>')