| |
| from django import forms |
| from django.conf import settings |
| from django.utils.html import escape |
| from django.utils.safestring import mark_safe |
| from django.utils.encoding import force_unicode |
| from django.contrib.admin.util import flatten_fieldsets |
| |
| class AdminForm(object): |
| def __init__(self, form, fieldsets, prepopulated_fields): |
| self.form, self.fieldsets = form, fieldsets |
| self.prepopulated_fields = [{ |
| 'field': form[field_name], |
| 'dependencies': [form[f] for f in dependencies] |
| } for field_name, dependencies in prepopulated_fields.items()] |
| |
| def __iter__(self): |
| for name, options in self.fieldsets: |
| yield Fieldset(self.form, name, **options) |
| |
| def first_field(self): |
| for bf in self.form: |
| return bf |
| |
| def _media(self): |
| media = self.form.media |
| for fs in self: |
| media = media + fs.media |
| return media |
| media = property(_media) |
| |
| class Fieldset(object): |
| def __init__(self, form, name=None, fields=(), classes=(), description=None): |
| self.form = form |
| self.name, self.fields = name, fields |
| self.classes = u' '.join(classes) |
| self.description = description |
| |
| def _media(self): |
| if 'collapse' in self.classes: |
| return forms.Media(js=['%sjs/admin/CollapsedFieldsets.js' % settings.ADMIN_MEDIA_PREFIX]) |
| return forms.Media() |
| media = property(_media) |
| |
| def __iter__(self): |
| for field in self.fields: |
| yield Fieldline(self.form, field) |
| |
| class Fieldline(object): |
| def __init__(self, form, field): |
| self.form = form # A django.forms.Form instance |
| if isinstance(field, basestring): |
| self.fields = [field] |
| else: |
| self.fields = field |
| |
| def __iter__(self): |
| for i, field in enumerate(self.fields): |
| yield AdminField(self.form, field, is_first=(i == 0)) |
| |
| def errors(self): |
| return mark_safe(u'\n'.join([self.form[f].errors.as_ul() for f in self.fields]).strip('\n')) |
| |
| class AdminField(object): |
| def __init__(self, form, field, is_first): |
| self.field = form[field] # A django.forms.BoundField instance |
| self.is_first = is_first # Whether this field is first on the line |
| self.is_checkbox = isinstance(self.field.field.widget, forms.CheckboxInput) |
| |
| def label_tag(self): |
| classes = [] |
| if self.is_checkbox: |
| classes.append(u'vCheckboxLabel') |
| contents = force_unicode(escape(self.field.label)) |
| else: |
| contents = force_unicode(escape(self.field.label)) + u':' |
| if self.field.field.required: |
| classes.append(u'required') |
| if not self.is_first: |
| classes.append(u'inline') |
| attrs = classes and {'class': u' '.join(classes)} or {} |
| return self.field.label_tag(contents=contents, attrs=attrs) |
| |
| class InlineAdminFormSet(object): |
| """ |
| A wrapper around an inline formset for use in the admin system. |
| """ |
| def __init__(self, inline, formset, fieldsets): |
| self.opts = inline |
| self.formset = formset |
| self.fieldsets = fieldsets |
| |
| def __iter__(self): |
| for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()): |
| yield InlineAdminForm(self.formset, form, self.fieldsets, self.opts.prepopulated_fields, original) |
| for form in self.formset.extra_forms: |
| yield InlineAdminForm(self.formset, form, self.fieldsets, self.opts.prepopulated_fields, None) |
| |
| def fields(self): |
| for field_name in flatten_fieldsets(self.fieldsets): |
| yield self.formset.form.base_fields[field_name] |
| |
| def _media(self): |
| media = self.opts.media + self.formset.media |
| for fs in self: |
| media = media + fs.media |
| return media |
| media = property(_media) |
| |
| class InlineAdminForm(AdminForm): |
| """ |
| A wrapper around an inline form for use in the admin system. |
| """ |
| def __init__(self, formset, form, fieldsets, prepopulated_fields, original): |
| self.formset = formset |
| self.original = original |
| self.show_url = original and hasattr(original, 'get_absolute_url') |
| super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields) |
| |
| def pk_field(self): |
| return AdminField(self.form, self.formset._pk_field_name, False) |
| |
| def deletion_field(self): |
| from django.forms.formsets import DELETION_FIELD_NAME |
| return AdminField(self.form, DELETION_FIELD_NAME, False) |
| |
| def ordering_field(self): |
| from django.forms.formsets import ORDERING_FIELD_NAME |
| return AdminField(self.form, ORDERING_FIELD_NAME, False) |
| |
| class AdminErrorList(forms.util.ErrorList): |
| """ |
| Stores all errors for the form/formsets in an add/change stage view. |
| """ |
| def __init__(self, form, inline_formsets): |
| if form.is_bound: |
| self.extend(form.errors.values()) |
| for inline_formset in inline_formsets: |
| self.extend(inline_formset.non_form_errors()) |
| for errors_in_inline_form in inline_formset.errors: |
| self.extend(errors_in_inline_form.values()) |