web/lib/django/contrib/admin/helpers.py
changeset 0 0d40e90630ef
child 29 cc9b7e14412b
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     1 
       
     2 from django import forms
       
     3 from django.conf import settings
       
     4 from django.utils.html import escape
       
     5 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 from django.utils.translation import ugettext_lazy as _
       
    10 
       
    11 ACTION_CHECKBOX_NAME = '_selected_action'
       
    12 
       
    13 class ActionForm(forms.Form):
       
    14     action = forms.ChoiceField(label=_('Action:'))
       
    15 
       
    16 checkbox = forms.CheckboxInput({'class': 'action-select'}, lambda value: False)
       
    17 
       
    18 class AdminForm(object):
       
    19     def __init__(self, form, fieldsets, prepopulated_fields):
       
    20         self.form, self.fieldsets = form, normalize_fieldsets(fieldsets)
       
    21         self.prepopulated_fields = [{
       
    22             'field': form[field_name],
       
    23             'dependencies': [form[f] for f in dependencies]
       
    24         } for field_name, dependencies in prepopulated_fields.items()]
       
    25 
       
    26     def __iter__(self):
       
    27         for name, options in self.fieldsets:
       
    28             yield Fieldset(self.form, name, **options)
       
    29 
       
    30     def first_field(self):
       
    31         try:
       
    32             fieldset_name, fieldset_options = self.fieldsets[0]
       
    33             field_name = fieldset_options['fields'][0]
       
    34             if not isinstance(field_name, basestring):
       
    35                 field_name = field_name[0]
       
    36             return self.form[field_name]
       
    37         except (KeyError, IndexError):
       
    38             pass
       
    39         try:
       
    40             return iter(self.form).next()
       
    41         except StopIteration:
       
    42             return None
       
    43 
       
    44     def _media(self):
       
    45         media = self.form.media
       
    46         for fs in self:
       
    47             media = media + fs.media
       
    48         return media
       
    49     media = property(_media)
       
    50 
       
    51 class Fieldset(object):
       
    52     def __init__(self, form, name=None, fields=(), classes=(), description=None):
       
    53         self.form = form
       
    54         self.name, self.fields = name, fields
       
    55         self.classes = u' '.join(classes)
       
    56         self.description = description
       
    57 
       
    58     def _media(self):
       
    59         if 'collapse' in self.classes:
       
    60             return forms.Media(js=['%sjs/admin/CollapsedFieldsets.js' % settings.ADMIN_MEDIA_PREFIX])
       
    61         return forms.Media()
       
    62     media = property(_media)
       
    63 
       
    64     def __iter__(self):
       
    65         for field in self.fields:
       
    66             yield Fieldline(self.form, field)
       
    67 
       
    68 class Fieldline(object):
       
    69     def __init__(self, form, field):
       
    70         self.form = form # A django.forms.Form instance
       
    71         if isinstance(field, basestring):
       
    72             self.fields = [field]
       
    73         else:
       
    74             self.fields = field
       
    75 
       
    76     def __iter__(self):
       
    77         for i, field in enumerate(self.fields):
       
    78             yield AdminField(self.form, field, is_first=(i == 0))
       
    79 
       
    80     def errors(self):
       
    81         return mark_safe(u'\n'.join([self.form[f].errors.as_ul() for f in self.fields]).strip('\n'))
       
    82 
       
    83 class AdminField(object):
       
    84     def __init__(self, form, field, is_first):
       
    85         self.field = form[field] # A django.forms.BoundField instance
       
    86         self.is_first = is_first # Whether this field is first on the line
       
    87         self.is_checkbox = isinstance(self.field.field.widget, forms.CheckboxInput)
       
    88 
       
    89     def label_tag(self):
       
    90         classes = []
       
    91         if self.is_checkbox:
       
    92             classes.append(u'vCheckboxLabel')
       
    93             contents = force_unicode(escape(self.field.label))
       
    94         else:
       
    95             contents = force_unicode(escape(self.field.label)) + u':'
       
    96         if self.field.field.required:
       
    97             classes.append(u'required')
       
    98         if not self.is_first:
       
    99             classes.append(u'inline')
       
   100         attrs = classes and {'class': u' '.join(classes)} or {}
       
   101         return self.field.label_tag(contents=contents, attrs=attrs)
       
   102 
       
   103 class InlineAdminFormSet(object):
       
   104     """
       
   105     A wrapper around an inline formset for use in the admin system.
       
   106     """
       
   107     def __init__(self, inline, formset, fieldsets):
       
   108         self.opts = inline
       
   109         self.formset = formset
       
   110         self.fieldsets = fieldsets
       
   111 
       
   112     def __iter__(self):
       
   113         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)
       
   115         for form in self.formset.extra_forms:
       
   116             yield InlineAdminForm(self.formset, form, self.fieldsets, self.opts.prepopulated_fields, None)
       
   117 
       
   118     def fields(self):
       
   119         fk = getattr(self.formset, "fk", None)
       
   120         for field_name in flatten_fieldsets(self.fieldsets):
       
   121             if fk and fk.name == field_name:
       
   122                 continue
       
   123             yield self.formset.form.base_fields[field_name]
       
   124 
       
   125     def _media(self):
       
   126         media = self.opts.media + self.formset.media
       
   127         for fs in self:
       
   128             media = media + fs.media
       
   129         return media
       
   130     media = property(_media)
       
   131 
       
   132 class InlineAdminForm(AdminForm):
       
   133     """
       
   134     A wrapper around an inline form for use in the admin system.
       
   135     """
       
   136     def __init__(self, formset, form, fieldsets, prepopulated_fields, original):
       
   137         self.formset = formset
       
   138         self.original = original
       
   139         if original is not None:
       
   140             self.original_content_type_id = ContentType.objects.get_for_model(original).pk
       
   141         self.show_url = original and hasattr(original, 'get_absolute_url')
       
   142         super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields)
       
   143 
       
   144     def __iter__(self):
       
   145         for name, options in self.fieldsets:
       
   146             yield InlineFieldset(self.formset, self.form, name, **options)
       
   147 
       
   148     def has_auto_field(self):
       
   149         if self.form._meta.model._meta.has_auto_field:
       
   150             return True
       
   151         # Also search any parents for an auto field.
       
   152         for parent in self.form._meta.model._meta.get_parent_list():
       
   153             if parent._meta.has_auto_field:
       
   154                 return True
       
   155         return False
       
   156 
       
   157     def field_count(self):
       
   158         # tabular.html uses this function for colspan value.
       
   159         num_of_fields = 0
       
   160         if self.has_auto_field():
       
   161             num_of_fields += 1
       
   162         num_of_fields += len(self.fieldsets[0][1]["fields"])
       
   163         if self.formset.can_order:
       
   164             num_of_fields += 1
       
   165         if self.formset.can_delete:
       
   166             num_of_fields += 1
       
   167         return num_of_fields
       
   168 
       
   169     def pk_field(self):
       
   170         return AdminField(self.form, self.formset._pk_field.name, False)
       
   171 
       
   172     def fk_field(self):
       
   173         fk = getattr(self.formset, "fk", None)
       
   174         if fk:
       
   175             return AdminField(self.form, fk.name, False)
       
   176         else:
       
   177             return ""
       
   178 
       
   179     def deletion_field(self):
       
   180         from django.forms.formsets import DELETION_FIELD_NAME
       
   181         return AdminField(self.form, DELETION_FIELD_NAME, False)
       
   182 
       
   183     def ordering_field(self):
       
   184         from django.forms.formsets import ORDERING_FIELD_NAME
       
   185         return AdminField(self.form, ORDERING_FIELD_NAME, False)
       
   186 
       
   187 class InlineFieldset(Fieldset):
       
   188     def __init__(self, formset, *args, **kwargs):
       
   189         self.formset = formset
       
   190         super(InlineFieldset, self).__init__(*args, **kwargs)
       
   191 
       
   192     def __iter__(self):
       
   193         fk = getattr(self.formset, "fk", None)
       
   194         for field in self.fields:
       
   195             if fk and fk.name == field:
       
   196                 continue
       
   197             yield Fieldline(self.form, field)
       
   198 
       
   199 class AdminErrorList(forms.util.ErrorList):
       
   200     """
       
   201     Stores all errors for the form/formsets in an add/change stage view.
       
   202     """
       
   203     def __init__(self, form, inline_formsets):
       
   204         if form.is_bound:
       
   205             self.extend(form.errors.values())
       
   206             for inline_formset in inline_formsets:
       
   207                 self.extend(inline_formset.non_form_errors())
       
   208                 for errors_in_inline_form in inline_formset.errors:
       
   209                     self.extend(errors_in_inline_form.values())
       
   210 
       
   211 def normalize_fieldsets(fieldsets):
       
   212     """
       
   213     Make sure the keys in fieldset dictionaries are strings. Returns the
       
   214     normalized data.
       
   215     """
       
   216     result = []
       
   217     for name, options in fieldsets:
       
   218         result.append((name, normalize_dictionary(options)))
       
   219     return result
       
   220 
       
   221 def normalize_dictionary(data_dict):
       
   222     """
       
   223     Converts all the keys in "data_dict" to strings. The keys must be
       
   224     convertible using str().
       
   225     """
       
   226     for key, value in data_dict.items():
       
   227         if not isinstance(key, str):
       
   228             del data_dict[key]
       
   229             data_dict[str(key)] = value
       
   230     return data_dict
       
   231