|
1 from datetime import datetime |
|
2 import unittest |
|
3 |
|
4 from django.conf import settings |
|
5 from django.db import models |
|
6 from django.utils.formats import localize |
|
7 from django.test import TestCase |
|
8 |
|
9 from django.contrib import admin |
|
10 from django.contrib.admin.util import display_for_field, label_for_field, lookup_field |
|
11 from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE |
|
12 from django.contrib.sites.models import Site |
|
13 from django.contrib.admin.util import NestedObjects |
|
14 |
|
15 from models import Article, Count, Event, Location |
|
16 |
|
17 |
|
18 class NestedObjectsTests(TestCase): |
|
19 """ |
|
20 Tests for ``NestedObject`` utility collection. |
|
21 |
|
22 """ |
|
23 def setUp(self): |
|
24 self.n = NestedObjects() |
|
25 self.objs = [Count.objects.create(num=i) for i in range(5)] |
|
26 |
|
27 def _check(self, target): |
|
28 self.assertEquals(self.n.nested(lambda obj: obj.num), target) |
|
29 |
|
30 def _add(self, obj, parent=None): |
|
31 # don't bother providing the extra args that NestedObjects ignores |
|
32 self.n.add(None, None, obj, None, parent) |
|
33 |
|
34 def test_unrelated_roots(self): |
|
35 self._add(self.objs[0]) |
|
36 self._add(self.objs[1]) |
|
37 self._add(self.objs[2], self.objs[1]) |
|
38 |
|
39 self._check([0, 1, [2]]) |
|
40 |
|
41 def test_siblings(self): |
|
42 self._add(self.objs[0]) |
|
43 self._add(self.objs[1], self.objs[0]) |
|
44 self._add(self.objs[2], self.objs[0]) |
|
45 |
|
46 self._check([0, [1, 2]]) |
|
47 |
|
48 def test_duplicate_instances(self): |
|
49 self._add(self.objs[0]) |
|
50 self._add(self.objs[1]) |
|
51 dupe = Count.objects.get(num=1) |
|
52 self._add(dupe, self.objs[0]) |
|
53 |
|
54 self._check([0, 1]) |
|
55 |
|
56 def test_non_added_parent(self): |
|
57 self._add(self.objs[0], self.objs[1]) |
|
58 |
|
59 self._check([0]) |
|
60 |
|
61 def test_cyclic(self): |
|
62 self._add(self.objs[0], self.objs[2]) |
|
63 self._add(self.objs[1], self.objs[0]) |
|
64 self._add(self.objs[2], self.objs[1]) |
|
65 self._add(self.objs[0], self.objs[2]) |
|
66 |
|
67 self._check([0, [1, [2]]]) |
|
68 |
|
69 |
|
70 class UtilTests(unittest.TestCase): |
|
71 def test_values_from_lookup_field(self): |
|
72 """ |
|
73 Regression test for #12654: lookup_field |
|
74 """ |
|
75 SITE_NAME = 'example.com' |
|
76 TITLE_TEXT = 'Some title' |
|
77 CREATED_DATE = datetime.min |
|
78 ADMIN_METHOD = 'admin method' |
|
79 SIMPLE_FUNCTION = 'function' |
|
80 INSTANCE_ATTRIBUTE = 'attr' |
|
81 |
|
82 class MockModelAdmin(object): |
|
83 def get_admin_value(self, obj): |
|
84 return ADMIN_METHOD |
|
85 |
|
86 simple_function = lambda obj: SIMPLE_FUNCTION |
|
87 |
|
88 article = Article( |
|
89 site=Site(domain=SITE_NAME), |
|
90 title=TITLE_TEXT, |
|
91 created=CREATED_DATE, |
|
92 ) |
|
93 article.non_field = INSTANCE_ATTRIBUTE |
|
94 |
|
95 verifications = ( |
|
96 ('site', SITE_NAME), |
|
97 ('created', localize(CREATED_DATE)), |
|
98 ('title', TITLE_TEXT), |
|
99 ('get_admin_value', ADMIN_METHOD), |
|
100 (simple_function, SIMPLE_FUNCTION), |
|
101 ('test_from_model', article.test_from_model()), |
|
102 ('non_field', INSTANCE_ATTRIBUTE) |
|
103 ) |
|
104 |
|
105 mock_admin = MockModelAdmin() |
|
106 for name, value in verifications: |
|
107 field, attr, resolved_value = lookup_field(name, article, mock_admin) |
|
108 |
|
109 if field is not None: |
|
110 resolved_value = display_for_field(resolved_value, field) |
|
111 |
|
112 self.assertEqual(value, resolved_value) |
|
113 |
|
114 def test_null_display_for_field(self): |
|
115 """ |
|
116 Regression test for #12550: display_for_field should handle None |
|
117 value. |
|
118 """ |
|
119 display_value = display_for_field(None, models.CharField()) |
|
120 self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) |
|
121 |
|
122 display_value = display_for_field(None, models.CharField( |
|
123 choices=( |
|
124 (None, "test_none"), |
|
125 ) |
|
126 )) |
|
127 self.assertEqual(display_value, "test_none") |
|
128 |
|
129 display_value = display_for_field(None, models.DateField()) |
|
130 self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) |
|
131 |
|
132 display_value = display_for_field(None, models.TimeField()) |
|
133 self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) |
|
134 |
|
135 # Regression test for #13071: NullBooleanField has special |
|
136 # handling. |
|
137 display_value = display_for_field(None, models.NullBooleanField()) |
|
138 expected = u'<img src="%simg/admin/icon-unknown.gif" alt="None" />' % settings.ADMIN_MEDIA_PREFIX |
|
139 self.assertEqual(display_value, expected) |
|
140 |
|
141 display_value = display_for_field(None, models.DecimalField()) |
|
142 self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) |
|
143 |
|
144 display_value = display_for_field(None, models.FloatField()) |
|
145 self.assertEqual(display_value, EMPTY_CHANGELIST_VALUE) |
|
146 |
|
147 def test_label_for_field(self): |
|
148 """ |
|
149 Tests for label_for_field |
|
150 """ |
|
151 self.assertEquals( |
|
152 label_for_field("title", Article), |
|
153 "title" |
|
154 ) |
|
155 self.assertEquals( |
|
156 label_for_field("title2", Article), |
|
157 "another name" |
|
158 ) |
|
159 self.assertEquals( |
|
160 label_for_field("title2", Article, return_attr=True), |
|
161 ("another name", None) |
|
162 ) |
|
163 |
|
164 self.assertEquals( |
|
165 label_for_field("__unicode__", Article), |
|
166 "article" |
|
167 ) |
|
168 self.assertEquals( |
|
169 label_for_field("__str__", Article), |
|
170 "article" |
|
171 ) |
|
172 |
|
173 self.assertRaises( |
|
174 AttributeError, |
|
175 lambda: label_for_field("unknown", Article) |
|
176 ) |
|
177 |
|
178 def test_callable(obj): |
|
179 return "nothing" |
|
180 self.assertEquals( |
|
181 label_for_field(test_callable, Article), |
|
182 "Test callable" |
|
183 ) |
|
184 self.assertEquals( |
|
185 label_for_field(test_callable, Article, return_attr=True), |
|
186 ("Test callable", test_callable) |
|
187 ) |
|
188 |
|
189 self.assertEquals( |
|
190 label_for_field("test_from_model", Article), |
|
191 "Test from model" |
|
192 ) |
|
193 self.assertEquals( |
|
194 label_for_field("test_from_model", Article, return_attr=True), |
|
195 ("Test from model", Article.test_from_model) |
|
196 ) |
|
197 self.assertEquals( |
|
198 label_for_field("test_from_model_with_override", Article), |
|
199 "not What you Expect" |
|
200 ) |
|
201 |
|
202 self.assertEquals( |
|
203 label_for_field(lambda x: "nothing", Article), |
|
204 "--" |
|
205 ) |
|
206 |
|
207 class MockModelAdmin(object): |
|
208 def test_from_model(self, obj): |
|
209 return "nothing" |
|
210 test_from_model.short_description = "not Really the Model" |
|
211 |
|
212 self.assertEquals( |
|
213 label_for_field("test_from_model", Article, model_admin=MockModelAdmin), |
|
214 "not Really the Model" |
|
215 ) |
|
216 self.assertEquals( |
|
217 label_for_field("test_from_model", Article, |
|
218 model_admin = MockModelAdmin, |
|
219 return_attr = True |
|
220 ), |
|
221 ("not Really the Model", MockModelAdmin.test_from_model) |
|
222 ) |
|
223 |
|
224 def test_related_name(self): |
|
225 """ |
|
226 Regression test for #13963 |
|
227 """ |
|
228 self.assertEquals( |
|
229 label_for_field('location', Event, return_attr=True), |
|
230 ('location', None), |
|
231 ) |
|
232 self.assertEquals( |
|
233 label_for_field('event', Location, return_attr=True), |
|
234 ('awesome event', None), |
|
235 ) |
|
236 self.assertEquals( |
|
237 label_for_field('guest', Event, return_attr=True), |
|
238 ('awesome guest', None), |
|
239 ) |