Hello site
[auf_framonde.git] / eggs / Django-1.4.5-py2.7.egg / django / contrib / admin / helpers.py
1 from django import forms
2 from django.contrib.admin.util import (flatten_fieldsets, lookup_field,
3 display_for_field, label_for_field, help_text_for_field)
4 from django.contrib.admin.templatetags.admin_static import static
5 from django.contrib.contenttypes.models import ContentType
6 from django.core.exceptions import ObjectDoesNotExist
7 from django.db.models.fields.related import ManyToManyRel
8 from django.forms.util import flatatt
9 from django.template.defaultfilters import capfirst
10 from django.utils.encoding import force_unicode, smart_unicode
11 from django.utils.html import escape, conditional_escape
12 from django.utils.safestring import mark_safe
13 from django.utils.translation import ugettext_lazy as _
14 from django.conf import settings
15
16
17 ACTION_CHECKBOX_NAME = '_selected_action'
18
19 class ActionForm(forms.Form):
20 action = forms.ChoiceField(label=_('Action:'))
21 select_across = forms.BooleanField(label='', required=False, initial=0,
22 widget=forms.HiddenInput({'class': 'select-across'}))
23
24 checkbox = forms.CheckboxInput({'class': 'action-select'}, lambda value: False)
25
26 class AdminForm(object):
27 def __init__(self, form, fieldsets, prepopulated_fields, readonly_fields=None, model_admin=None):
28 self.form, self.fieldsets = form, normalize_fieldsets(fieldsets)
29 self.prepopulated_fields = [{
30 'field': form[field_name],
31 'dependencies': [form[f] for f in dependencies]
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
37
38 def __iter__(self):
39 for name, options in self.fieldsets:
40 yield Fieldset(self.form, name,
41 readonly_fields=self.readonly_fields,
42 model_admin=self.model_admin,
43 **options
44 )
45
46 def first_field(self):
47 try:
48 fieldset_name, fieldset_options = self.fieldsets[0]
49 field_name = fieldset_options['fields'][0]
50 if not isinstance(field_name, basestring):
51 field_name = field_name[0]
52 return self.form[field_name]
53 except (KeyError, IndexError):
54 pass
55 try:
56 return iter(self.form).next()
57 except StopIteration:
58 return None
59
60 def _media(self):
61 media = self.form.media
62 for fs in self:
63 media = media + fs.media
64 return media
65 media = property(_media)
66
67 class Fieldset(object):
68 def __init__(self, form, name=None, readonly_fields=(), fields=(), classes=(),
69 description=None, model_admin=None):
70 self.form = form
71 self.name, self.fields = name, fields
72 self.classes = u' '.join(classes)
73 self.description = description
74 self.model_admin = model_admin
75 self.readonly_fields = readonly_fields
76
77 def _media(self):
78 if 'collapse' in self.classes:
79 extra = '' if settings.DEBUG else '.min'
80 js = ['jquery%s.js' % extra,
81 'jquery.init.js',
82 'collapse%s.js' % extra]
83 return forms.Media(js=[static('admin/js/%s' % url) for url in js])
84 return forms.Media()
85 media = property(_media)
86
87 def __iter__(self):
88 for field in self.fields:
89 yield Fieldline(self.form, field, self.readonly_fields, model_admin=self.model_admin)
90
91 class Fieldline(object):
92 def __init__(self, form, field, readonly_fields=None, model_admin=None):
93 self.form = form # A django.forms.Form instance
94 if not hasattr(field, "__iter__"):
95 self.fields = [field]
96 else:
97 self.fields = field
98 self.model_admin = model_admin
99 if readonly_fields is None:
100 readonly_fields = ()
101 self.readonly_fields = readonly_fields
102
103 def __iter__(self):
104 for i, field in enumerate(self.fields):
105 if field in self.readonly_fields:
106 yield AdminReadonlyField(self.form, field, is_first=(i == 0),
107 model_admin=self.model_admin)
108 else:
109 yield AdminField(self.form, field, is_first=(i == 0))
110
111 def errors(self):
112 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'))
113
114 class AdminField(object):
115 def __init__(self, form, field, is_first):
116 self.field = form[field] # A django.forms.BoundField instance
117 self.is_first = is_first # Whether this field is first on the line
118 self.is_checkbox = isinstance(self.field.field.widget, forms.CheckboxInput)
119
120 def label_tag(self):
121 classes = []
122 contents = conditional_escape(force_unicode(self.field.label))
123 if self.is_checkbox:
124 classes.append(u'vCheckboxLabel')
125 else:
126 contents += u':'
127 if self.field.field.required:
128 classes.append(u'required')
129 if not self.is_first:
130 classes.append(u'inline')
131 attrs = classes and {'class': u' '.join(classes)} or {}
132 return self.field.label_tag(contents=mark_safe(contents), attrs=attrs)
133
134 def errors(self):
135 return mark_safe(self.field.errors.as_ul())
136
137 class AdminReadonlyField(object):
138 def __init__(self, form, field, is_first, model_admin=None):
139 label = label_for_field(field, form._meta.model, model_admin)
140 # Make self.field look a little bit like a field. This means that
141 # {{ field.name }} must be a useful class name to identify the field.
142 # For convenience, store other field-related data here too.
143 if callable(field):
144 class_name = field.__name__ != '<lambda>' and field.__name__ or ''
145 else:
146 class_name = field
147 self.field = {
148 'name': class_name,
149 'label': label,
150 'field': field,
151 'help_text': help_text_for_field(class_name, form._meta.model)
152 }
153 self.form = form
154 self.model_admin = model_admin
155 self.is_first = is_first
156 self.is_checkbox = False
157 self.is_readonly = True
158
159 def label_tag(self):
160 attrs = {}
161 if not self.is_first:
162 attrs["class"] = "inline"
163 label = self.field['label']
164 contents = capfirst(force_unicode(escape(label))) + u":"
165 return mark_safe('<label%(attrs)s>%(contents)s</label>' % {
166 "attrs": flatatt(attrs),
167 "contents": contents,
168 })
169
170 def contents(self):
171 from django.contrib.admin.templatetags.admin_list import _boolean_icon
172 from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
173 field, obj, model_admin = self.field['field'], self.form.instance, self.model_admin
174 try:
175 f, attr, value = lookup_field(field, obj, model_admin)
176 except (AttributeError, ValueError, ObjectDoesNotExist):
177 result_repr = EMPTY_CHANGELIST_VALUE
178 else:
179 if f is None:
180 boolean = getattr(attr, "boolean", False)
181 if boolean:
182 result_repr = _boolean_icon(value)
183 else:
184 result_repr = smart_unicode(value)
185 if getattr(attr, "allow_tags", False):
186 result_repr = mark_safe(result_repr)
187 else:
188 if value is None:
189 result_repr = EMPTY_CHANGELIST_VALUE
190 elif isinstance(f.rel, ManyToManyRel):
191 result_repr = ", ".join(map(unicode, value.all()))
192 else:
193 result_repr = display_for_field(value, f)
194 return conditional_escape(result_repr)
195
196 class InlineAdminFormSet(object):
197 """
198 A wrapper around an inline formset for use in the admin system.
199 """
200 def __init__(self, inline, formset, fieldsets, prepopulated_fields=None,
201 readonly_fields=None, model_admin=None):
202 self.opts = inline
203 self.formset = formset
204 self.fieldsets = fieldsets
205 self.model_admin = model_admin
206 if readonly_fields is None:
207 readonly_fields = ()
208 self.readonly_fields = readonly_fields
209 if prepopulated_fields is None:
210 prepopulated_fields = {}
211 self.prepopulated_fields = prepopulated_fields
212
213 def __iter__(self):
214 for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()):
215 yield InlineAdminForm(self.formset, form, self.fieldsets,
216 self.prepopulated_fields, original, self.readonly_fields,
217 model_admin=self.opts)
218 for form in self.formset.extra_forms:
219 yield InlineAdminForm(self.formset, form, self.fieldsets,
220 self.prepopulated_fields, None, self.readonly_fields,
221 model_admin=self.opts)
222 yield InlineAdminForm(self.formset, self.formset.empty_form,
223 self.fieldsets, self.prepopulated_fields, None,
224 self.readonly_fields, model_admin=self.opts)
225
226 def fields(self):
227 fk = getattr(self.formset, "fk", None)
228 for i, field in enumerate(flatten_fieldsets(self.fieldsets)):
229 if fk and fk.name == field:
230 continue
231 if field in self.readonly_fields:
232 yield {
233 'label': label_for_field(field, self.opts.model, self.opts),
234 'widget': {
235 'is_hidden': False
236 },
237 'required': False
238 }
239 else:
240 yield self.formset.form.base_fields[field]
241
242 def _media(self):
243 media = self.opts.media + self.formset.media
244 for fs in self:
245 media = media + fs.media
246 return media
247 media = property(_media)
248
249 class InlineAdminForm(AdminForm):
250 """
251 A wrapper around an inline form for use in the admin system.
252 """
253 def __init__(self, formset, form, fieldsets, prepopulated_fields, original,
254 readonly_fields=None, model_admin=None):
255 self.formset = formset
256 self.model_admin = model_admin
257 self.original = original
258 if original is not None:
259 self.original_content_type_id = ContentType.objects.get_for_model(original).pk
260 self.show_url = original and hasattr(original, 'get_absolute_url')
261 super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields,
262 readonly_fields, model_admin)
263
264 def __iter__(self):
265 for name, options in self.fieldsets:
266 yield InlineFieldset(self.formset, self.form, name,
267 self.readonly_fields, model_admin=self.model_admin, **options)
268
269 def has_auto_field(self):
270 if self.form._meta.model._meta.has_auto_field:
271 return True
272 # Also search any parents for an auto field.
273 for parent in self.form._meta.model._meta.get_parent_list():
274 if parent._meta.has_auto_field:
275 return True
276 return False
277
278 def field_count(self):
279 # tabular.html uses this function for colspan value.
280 num_of_fields = 0
281 if self.has_auto_field():
282 num_of_fields += 1
283 num_of_fields += len(self.fieldsets[0][1]["fields"])
284 if self.formset.can_order:
285 num_of_fields += 1
286 if self.formset.can_delete:
287 num_of_fields += 1
288 return num_of_fields
289
290 def pk_field(self):
291 return AdminField(self.form, self.formset._pk_field.name, False)
292
293 def fk_field(self):
294 fk = getattr(self.formset, "fk", None)
295 if fk:
296 return AdminField(self.form, fk.name, False)
297 else:
298 return ""
299
300 def deletion_field(self):
301 from django.forms.formsets import DELETION_FIELD_NAME
302 return AdminField(self.form, DELETION_FIELD_NAME, False)
303
304 def ordering_field(self):
305 from django.forms.formsets import ORDERING_FIELD_NAME
306 return AdminField(self.form, ORDERING_FIELD_NAME, False)
307
308 class InlineFieldset(Fieldset):
309 def __init__(self, formset, *args, **kwargs):
310 self.formset = formset
311 super(InlineFieldset, self).__init__(*args, **kwargs)
312
313 def __iter__(self):
314 fk = getattr(self.formset, "fk", None)
315 for field in self.fields:
316 if fk and fk.name == field:
317 continue
318 yield Fieldline(self.form, field, self.readonly_fields,
319 model_admin=self.model_admin)
320
321 class AdminErrorList(forms.util.ErrorList):
322 """
323 Stores all errors for the form/formsets in an add/change stage view.
324 """
325 def __init__(self, form, inline_formsets):
326 if form.is_bound:
327 self.extend(form.errors.values())
328 for inline_formset in inline_formsets:
329 self.extend(inline_formset.non_form_errors())
330 for errors_in_inline_form in inline_formset.errors:
331 self.extend(errors_in_inline_form.values())
332
333 def normalize_fieldsets(fieldsets):
334 """
335 Make sure the keys in fieldset dictionaries are strings. Returns the
336 normalized data.
337 """
338 result = []
339 for name, options in fieldsets:
340 result.append((name, normalize_dictionary(options)))
341 return result
342
343 def normalize_dictionary(data_dict):
344 """
345 Converts all the keys in "data_dict" to strings. The keys must be
346 convertible using str().
347 """
348 for key, value in data_dict.items():
349 if not isinstance(key, str):
350 del data_dict[key]
351 data_dict[str(key)] = value
352 return data_dict