~ubuntu-branches/ubuntu/quantal/python-django/quantal-security

« back to all changes in this revision

Viewing changes to django/contrib/admin/helpers.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2010-05-21 07:52:55 UTC
  • mfrom: (1.3.6 upstream)
  • mto: This revision was merged to the branch mainline in revision 28.
  • Revision ID: james.westby@ubuntu.com-20100521075255-ii78v1dyfmyu3uzx
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
1
from django import forms
3
2
from django.conf import settings
4
 
from django.utils.html import escape
 
3
from django.contrib.admin.util import flatten_fieldsets, lookup_field
 
4
from django.contrib.admin.util import display_for_field, label_for_field
 
5
from django.contrib.contenttypes.models import ContentType
 
6
from django.core.exceptions import ObjectDoesNotExist
 
7
from django.db.models.fields import FieldDoesNotExist
 
8
from django.db.models.fields.related import ManyToManyRel
 
9
from django.forms.util import flatatt
 
10
from django.template.defaultfilters import capfirst
 
11
from django.utils.encoding import force_unicode, smart_unicode
 
12
from django.utils.html import escape, conditional_escape
5
13
from django.utils.safestring import mark_safe
6
 
from django.utils.encoding import force_unicode
7
 
from django.contrib.admin.util import flatten_fieldsets
8
 
from django.contrib.contenttypes.models import ContentType
9
14
from django.utils.translation import ugettext_lazy as _
10
15
 
 
16
 
11
17
ACTION_CHECKBOX_NAME = '_selected_action'
12
18
 
13
19
class ActionForm(forms.Form):
14
20
    action = forms.ChoiceField(label=_('Action:'))
 
21
    select_across = forms.BooleanField(label='', required=False, initial=0,
 
22
        widget=forms.HiddenInput({'class': 'select-across'}))
15
23
 
16
24
checkbox = forms.CheckboxInput({'class': 'action-select'}, lambda value: False)
17
25
 
18
26
class AdminForm(object):
19
 
    def __init__(self, form, fieldsets, prepopulated_fields):
 
27
    def __init__(self, form, fieldsets, prepopulated_fields, readonly_fields=None, model_admin=None):
20
28
        self.form, self.fieldsets = form, normalize_fieldsets(fieldsets)
21
29
        self.prepopulated_fields = [{
22
30
            'field': form[field_name],
23
31
            'dependencies': [form[f] for f in dependencies]
24
32
        } for field_name, dependencies in prepopulated_fields.items()]
 
33
        self.model_admin = model_admin
 
34
        if readonly_fields is None:
 
35
            readonly_fields = ()
 
36
        self.readonly_fields = readonly_fields
25
37
 
26
38
    def __iter__(self):
27
39
        for name, options in self.fieldsets:
28
 
            yield Fieldset(self.form, name, **options)
 
40
            yield Fieldset(self.form, name,
 
41
                readonly_fields=self.readonly_fields,
 
42
                model_admin=self.model_admin,
 
43
                **options
 
44
            )
29
45
 
30
46
    def first_field(self):
31
47
        try:
49
65
    media = property(_media)
50
66
 
51
67
class Fieldset(object):
52
 
    def __init__(self, form, name=None, fields=(), classes=(), description=None):
 
68
    def __init__(self, form, name=None, readonly_fields=(), fields=(), classes=(),
 
69
      description=None, model_admin=None):
53
70
        self.form = form
54
71
        self.name, self.fields = name, fields
55
72
        self.classes = u' '.join(classes)
56
73
        self.description = description
 
74
        self.model_admin = model_admin
 
75
        self.readonly_fields = readonly_fields
57
76
 
58
77
    def _media(self):
59
78
        if 'collapse' in self.classes:
60
 
            return forms.Media(js=['%sjs/admin/CollapsedFieldsets.js' % settings.ADMIN_MEDIA_PREFIX])
 
79
            js = ['js/jquery.min.js', 'js/jquery.init.js', 'js/collapse.min.js']
 
80
            return forms.Media(js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js])
61
81
        return forms.Media()
62
82
    media = property(_media)
63
83
 
64
84
    def __iter__(self):
65
85
        for field in self.fields:
66
 
            yield Fieldline(self.form, field)
 
86
            yield Fieldline(self.form, field, self.readonly_fields, model_admin=self.model_admin)
67
87
 
68
88
class Fieldline(object):
69
 
    def __init__(self, form, field):
 
89
    def __init__(self, form, field, readonly_fields=None, model_admin=None):
70
90
        self.form = form # A django.forms.Form instance
71
 
        if isinstance(field, basestring):
 
91
        if not hasattr(field, "__iter__"):
72
92
            self.fields = [field]
73
93
        else:
74
94
            self.fields = field
 
95
        self.model_admin = model_admin
 
96
        if readonly_fields is None:
 
97
            readonly_fields = ()
 
98
        self.readonly_fields = readonly_fields
75
99
 
76
100
    def __iter__(self):
77
101
        for i, field in enumerate(self.fields):
78
 
            yield AdminField(self.form, field, is_first=(i == 0))
 
102
            if field in self.readonly_fields:
 
103
                yield AdminReadonlyField(self.form, field, is_first=(i == 0),
 
104
                    model_admin=self.model_admin)
 
105
            else:
 
106
                yield AdminField(self.form, field, is_first=(i == 0))
79
107
 
80
108
    def errors(self):
81
 
        return mark_safe(u'\n'.join([self.form[f].errors.as_ul() for f in self.fields]).strip('\n'))
 
109
        return mark_safe(u'\n'.join([self.form[f].errors.as_ul() for f in self.fields if f not in self.readonly_fields]).strip('\n'))
82
110
 
83
111
class AdminField(object):
84
112
    def __init__(self, form, field, is_first):
100
128
        attrs = classes and {'class': u' '.join(classes)} or {}
101
129
        return self.field.label_tag(contents=contents, attrs=attrs)
102
130
 
 
131
class AdminReadonlyField(object):
 
132
    def __init__(self, form, field, is_first, model_admin=None):
 
133
        label = label_for_field(field, form._meta.model, model_admin)
 
134
        # Make self.field look a little bit like a field. This means that
 
135
        # {{ field.name }} must be a useful class name to identify the field.
 
136
        # For convenience, store other field-related data here too.
 
137
        if callable(field):
 
138
            class_name = field.__name__ != '<lambda>' and field.__name__ or ''
 
139
        else:
 
140
            class_name = field
 
141
        self.field = {
 
142
            'name': class_name,
 
143
            'label': label,
 
144
            'field': field,
 
145
        }
 
146
        self.form = form
 
147
        self.model_admin = model_admin
 
148
        self.is_first = is_first
 
149
        self.is_checkbox = False
 
150
        self.is_readonly = True
 
151
 
 
152
    def label_tag(self):
 
153
        attrs = {}
 
154
        if not self.is_first:
 
155
            attrs["class"] = "inline"
 
156
        label = self.field['label']
 
157
        contents = capfirst(force_unicode(escape(label))) + u":"
 
158
        return mark_safe('<label%(attrs)s>%(contents)s</label>' % {
 
159
            "attrs": flatatt(attrs),
 
160
            "contents": contents,
 
161
        })
 
162
 
 
163
    def contents(self):
 
164
        from django.contrib.admin.templatetags.admin_list import _boolean_icon
 
165
        from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
 
166
        field, obj, model_admin = self.field['field'], self.form.instance, self.model_admin
 
167
        try:
 
168
            f, attr, value = lookup_field(field, obj, model_admin)
 
169
        except (AttributeError, ValueError, ObjectDoesNotExist):
 
170
            result_repr = EMPTY_CHANGELIST_VALUE
 
171
        else:
 
172
            if f is None:
 
173
                boolean = getattr(attr, "boolean", False)
 
174
                if boolean:
 
175
                    result_repr = _boolean_icon(value)
 
176
                else:
 
177
                    result_repr = smart_unicode(value)
 
178
                    if getattr(attr, "allow_tags", False):
 
179
                        result_repr = mark_safe(result_repr)
 
180
            else:
 
181
                if value is None:
 
182
                    result_repr = EMPTY_CHANGELIST_VALUE
 
183
                elif isinstance(f.rel, ManyToManyRel):
 
184
                    result_repr = ", ".join(map(unicode, value.all()))
 
185
                else:
 
186
                    result_repr = display_for_field(value, f)
 
187
        return conditional_escape(result_repr)
 
188
 
103
189
class InlineAdminFormSet(object):
104
190
    """
105
191
    A wrapper around an inline formset for use in the admin system.
106
192
    """
107
 
    def __init__(self, inline, formset, fieldsets):
 
193
    def __init__(self, inline, formset, fieldsets, readonly_fields=None, model_admin=None):
108
194
        self.opts = inline
109
195
        self.formset = formset
110
196
        self.fieldsets = fieldsets
 
197
        self.model_admin = model_admin
 
198
        if readonly_fields is None:
 
199
            readonly_fields = ()
 
200
        self.readonly_fields = readonly_fields
111
201
 
112
202
    def __iter__(self):
113
203
        for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()):
114
 
            yield InlineAdminForm(self.formset, form, self.fieldsets, self.opts.prepopulated_fields, original)
 
204
            yield InlineAdminForm(self.formset, form, self.fieldsets,
 
205
                self.opts.prepopulated_fields, original, self.readonly_fields,
 
206
                model_admin=self.model_admin)
115
207
        for form in self.formset.extra_forms:
116
 
            yield InlineAdminForm(self.formset, form, self.fieldsets, self.opts.prepopulated_fields, None)
 
208
            yield InlineAdminForm(self.formset, form, self.fieldsets,
 
209
                self.opts.prepopulated_fields, None, self.readonly_fields,
 
210
                model_admin=self.model_admin)
 
211
        yield InlineAdminForm(self.formset, self.formset.empty_form,
 
212
            self.fieldsets, self.opts.prepopulated_fields, None,
 
213
            self.readonly_fields, model_admin=self.model_admin)
117
214
 
118
215
    def fields(self):
119
216
        fk = getattr(self.formset, "fk", None)
120
 
        for field_name in flatten_fieldsets(self.fieldsets):
121
 
            if fk and fk.name == field_name:
 
217
        for i, field in enumerate(flatten_fieldsets(self.fieldsets)):
 
218
            if fk and fk.name == field:
122
219
                continue
123
 
            yield self.formset.form.base_fields[field_name]
 
220
            if field in self.readonly_fields:
 
221
                yield {
 
222
                    'label': label_for_field(field, self.opts.model, self.model_admin),
 
223
                    'widget': {
 
224
                        'is_hidden': False
 
225
                    },
 
226
                    'required': False
 
227
                }
 
228
            else:
 
229
                yield self.formset.form.base_fields[field]
124
230
 
125
231
    def _media(self):
126
232
        media = self.opts.media + self.formset.media
133
239
    """
134
240
    A wrapper around an inline form for use in the admin system.
135
241
    """
136
 
    def __init__(self, formset, form, fieldsets, prepopulated_fields, original):
 
242
    def __init__(self, formset, form, fieldsets, prepopulated_fields, original,
 
243
      readonly_fields=None, model_admin=None):
137
244
        self.formset = formset
 
245
        self.model_admin = model_admin
138
246
        self.original = original
139
247
        if original is not None:
140
248
            self.original_content_type_id = ContentType.objects.get_for_model(original).pk
141
249
        self.show_url = original and hasattr(original, 'get_absolute_url')
142
 
        super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields)
 
250
        super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields,
 
251
            readonly_fields, model_admin)
143
252
 
144
253
    def __iter__(self):
145
254
        for name, options in self.fieldsets:
146
 
            yield InlineFieldset(self.formset, self.form, name, **options)
 
255
            yield InlineFieldset(self.formset, self.form, name,
 
256
                self.readonly_fields, model_admin=self.model_admin, **options)
147
257
 
148
258
    def has_auto_field(self):
149
259
        if self.form._meta.model._meta.has_auto_field:
194
304
        for field in self.fields:
195
305
            if fk and fk.name == field:
196
306
                continue
197
 
            yield Fieldline(self.form, field)
 
307
            yield Fieldline(self.form, field, self.readonly_fields,
 
308
                model_admin=self.model_admin)
198
309
 
199
310
class AdminErrorList(forms.util.ErrorList):
200
311
    """
228
339
            del data_dict[key]
229
340
            data_dict[str(key)] = value
230
341
    return data_dict
231