diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 1f8ff6d..7a4f814 100644
a
|
b
|
class ModelAdmin(BaseModelAdmin):
|
1081 | 1081 | 'actions_on_top': self.actions_on_top, |
1082 | 1082 | 'actions_on_bottom': self.actions_on_bottom, |
1083 | 1083 | 'actions_selection_counter': self.actions_selection_counter, |
| 1084 | 'request': request, |
1084 | 1085 | } |
1085 | 1086 | context.update(extra_context or {}) |
1086 | 1087 | context_instance = template.RequestContext(request, current_app=self.admin_site.name) |
diff --git a/django/contrib/admin/templates/admin/change_list.html b/django/contrib/admin/templates/admin/change_list.html
index 3b037e5..f319c95 100644
a
|
b
|
|
92 | 92 | |
93 | 93 | {% block result_list %} |
94 | 94 | {% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %} |
95 | | {% result_list cl %} |
| 95 | {% result_list request cl %} |
96 | 96 | {% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %} |
97 | 97 | {% endblock %} |
98 | 98 | {% block pagination %}{% pagination cl %}{% endblock %} |
diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py
index 565db32..32b5940 100644
a
|
b
|
def _boolean_icon(field_val):
|
126 | 126 | BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'} |
127 | 127 | return mark_safe(u'<img src="%simg/admin/icon-%s.gif" alt="%s" />' % (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)) |
128 | 128 | |
129 | | def items_for_result(cl, result, form): |
| 129 | def items_for_result(request, cl, result, form): |
130 | 130 | """ |
131 | 131 | Generates the actual list of data. |
132 | 132 | """ |
… |
… |
def items_for_result(cl, result, form):
|
135 | 135 | for field_name in cl.list_display: |
136 | 136 | row_class = '' |
137 | 137 | try: |
138 | | f, attr, value = lookup_field(field_name, result, cl.model_admin) |
| 138 | f, attr, value = lookup_field(field_name, result, cl.model_admin, request) |
139 | 139 | except (AttributeError, ObjectDoesNotExist): |
140 | 140 | result_repr = EMPTY_CHANGELIST_VALUE |
141 | 141 | else: |
… |
… |
def items_for_result(cl, result, form):
|
192 | 192 | if form: |
193 | 193 | yield mark_safe(u'<td>%s</td>' % force_unicode(form[cl.model._meta.pk.name])) |
194 | 194 | |
195 | | def results(cl): |
| 195 | def results(request, cl): |
196 | 196 | if cl.formset: |
197 | 197 | for res, form in zip(cl.result_list, cl.formset.forms): |
198 | | yield list(items_for_result(cl, res, form)) |
| 198 | yield list(items_for_result(request, cl, res, form)) |
199 | 199 | else: |
200 | 200 | for res in cl.result_list: |
201 | | yield list(items_for_result(cl, res, None)) |
| 201 | yield list(items_for_result(request, cl, res, None)) |
202 | 202 | |
203 | | def result_list(cl): |
| 203 | def result_list(request, cl): |
204 | 204 | """ |
205 | 205 | Displays the headers and data list together |
206 | 206 | """ |
207 | 207 | return {'cl': cl, |
208 | 208 | 'result_headers': list(result_headers(cl)), |
209 | | 'results': list(results(cl))} |
| 209 | 'results': list(results(request, cl))} |
210 | 210 | result_list = register.inclusion_tag("admin/change_list_results.html")(result_list) |
211 | 211 | |
212 | 212 | def date_hierarchy(cl): |
diff --git a/django/contrib/admin/util.py b/django/contrib/admin/util.py
index 776a6f0..97393f8 100644
a
|
b
|
def model_ngettext(obj, n=None):
|
250 | 250 | singular, plural = d["verbose_name"], d["verbose_name_plural"] |
251 | 251 | return ungettext(singular, plural, n or 0) |
252 | 252 | |
253 | | def lookup_field(name, obj, model_admin=None): |
| 253 | def lookup_field(name, obj, model_admin=None, request=None): |
254 | 254 | opts = obj._meta |
255 | 255 | try: |
256 | 256 | f = opts.get_field(name) |
… |
… |
def lookup_field(name, obj, model_admin=None):
|
258 | 258 | # For non-field values, the value is either a method, property or |
259 | 259 | # returned via a callable. |
260 | 260 | if callable(name): |
261 | | attr = name |
262 | | value = attr(obj) |
| 261 | attr = func = name |
263 | 262 | elif (model_admin is not None and hasattr(model_admin, name) and |
264 | 263 | not name == '__str__' and not name == '__unicode__'): |
265 | | attr = getattr(model_admin, name) |
266 | | value = attr(obj) |
| 264 | attr = func = getattr(model_admin, name) |
267 | 265 | else: |
268 | 266 | attr = getattr(obj, name) |
269 | 267 | if callable(attr): |
270 | | value = attr() |
| 268 | func = getattr(obj.__class__, name) |
271 | 269 | else: |
272 | | value = attr |
| 270 | def func(*args): return attr |
| 271 | |
| 272 | if getattr(attr, 'accepts_request', False): |
| 273 | value = func(obj, request) |
| 274 | else: |
| 275 | value = func(obj) |
| 276 | |
273 | 277 | f = None |
274 | 278 | else: |
275 | 279 | attr = None |
diff --git a/tests/regressiontests/admin_changelist/tests.py b/tests/regressiontests/admin_changelist/tests.py
index b70d7c5..3bc0d92 100644
a
|
b
|
class ChangeListTests(unittest.TestCase):
|
31 | 31 | m.list_select_related, m.list_per_page, m.list_editable, m) |
32 | 32 | FormSet = m.get_changelist_formset(request) |
33 | 33 | cl.formset = FormSet(queryset=cl.result_list) |
34 | | template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}') |
35 | | context = Context({'cl': cl}) |
| 34 | template = Template('{% load admin_list %}{% spaceless %}{% result_list request cl %}{% endspaceless %}') |
| 35 | context = Context({'request': request, 'cl': cl}) |
36 | 36 | table_output = template.render(context) |
37 | 37 | hidden_input_elem = '<input type="hidden" name="form-0-id" value="1" id="id_form-0-id" />' |
38 | 38 | self.failIf(table_output.find(hidden_input_elem) == -1, |
… |
… |
class ChangeListTests(unittest.TestCase):
|
49 | 49 | m.list_select_related, m.list_per_page, m.list_editable, m) |
50 | 50 | FormSet = m.get_changelist_formset(request) |
51 | 51 | cl.formset = FormSet(queryset=cl.result_list) |
52 | | template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}') |
53 | | context = Context({'cl': cl}) |
| 52 | template = Template('{% load admin_list %}{% spaceless %}{% result_list request cl %}{% endspaceless %}') |
| 53 | context = Context({'request': request, 'cl': cl}) |
54 | 54 | table_output = template.render(context) |
55 | 55 | self.failIf(table_output.find(hidden_input_elem) == -1, |
56 | 56 | 'Failed to find expected hidden input element in: %s' % table_output) |
diff --git a/tests/regressiontests/admin_util/tests.py b/tests/regressiontests/admin_util/tests.py
index 5ea0ac5..b118742 100644
a
|
b
|
class UtilTests(unittest.TestCase):
|
83 | 83 | def get_admin_value(self, obj): |
84 | 84 | return ADMIN_METHOD |
85 | 85 | |
| 86 | class MockRequest(object): |
| 87 | pass |
| 88 | |
86 | 89 | simple_function = lambda obj: SIMPLE_FUNCTION |
87 | 90 | |
| 91 | request_function = lambda obj, req: repr(req) |
| 92 | request_function.accepts_request = True |
| 93 | |
| 94 | request = MockRequest() |
| 95 | |
88 | 96 | article = Article( |
89 | 97 | site=Site(domain=SITE_NAME), |
90 | 98 | title=TITLE_TEXT, |
… |
… |
class UtilTests(unittest.TestCase):
|
98 | 106 | ('title', TITLE_TEXT), |
99 | 107 | ('get_admin_value', ADMIN_METHOD), |
100 | 108 | (simple_function, SIMPLE_FUNCTION), |
| 109 | (request_function, repr(request)), |
101 | 110 | ('test_from_model', article.test_from_model()), |
102 | 111 | ('non_field', INSTANCE_ATTRIBUTE) |
103 | 112 | ) |
104 | 113 | |
105 | 114 | mock_admin = MockModelAdmin() |
106 | 115 | for name, value in verifications: |
107 | | field, attr, resolved_value = lookup_field(name, article, mock_admin) |
| 116 | field, attr, resolved_value = lookup_field(name, article, mock_admin, request) |
108 | 117 | |
109 | 118 | if field is not None: |
110 | 119 | resolved_value = display_for_field(resolved_value, field) |