Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Moved admin form helpers to their own module to clean-up django/contr…

…ib/admin/options.py a little bit.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8433 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 62aafd8e3001b502bf7ee15ada53c6d440524a5d 1 parent ee7a5cd
Brian Rosner authored August 18, 2008
141  django/contrib/admin/helpers.py
... ...
@@ -0,0 +1,141 @@
  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
+
  9
+class AdminForm(object):
  10
+    def __init__(self, form, fieldsets, prepopulated_fields):
  11
+        self.form, self.fieldsets = form, fieldsets
  12
+        self.prepopulated_fields = [{
  13
+            'field': form[field_name],
  14
+            'dependencies': [form[f] for f in dependencies]
  15
+        } for field_name, dependencies in prepopulated_fields.items()]
  16
+
  17
+    def __iter__(self):
  18
+        for name, options in self.fieldsets:
  19
+            yield Fieldset(self.form, name, **options)
  20
+
  21
+    def first_field(self):
  22
+        for bf in self.form:
  23
+            return bf
  24
+
  25
+    def _media(self):
  26
+        media = self.form.media
  27
+        for fs in self:
  28
+            media = media + fs.media
  29
+        return media
  30
+    media = property(_media)
  31
+
  32
+class Fieldset(object):
  33
+    def __init__(self, form, name=None, fields=(), classes=(), description=None):
  34
+        self.form = form
  35
+        self.name, self.fields = name, fields
  36
+        self.classes = u' '.join(classes)
  37
+        self.description = description
  38
+
  39
+    def _media(self):
  40
+        if 'collapse' in self.classes:
  41
+            return forms.Media(js=['%sjs/admin/CollapsedFieldsets.js' % settings.ADMIN_MEDIA_PREFIX])
  42
+        return forms.Media()
  43
+    media = property(_media)
  44
+
  45
+    def __iter__(self):
  46
+        for field in self.fields:
  47
+            yield Fieldline(self.form, field)
  48
+
  49
+class Fieldline(object):
  50
+    def __init__(self, form, field):
  51
+        self.form = form # A django.forms.Form instance
  52
+        if isinstance(field, basestring):
  53
+            self.fields = [field]
  54
+        else:
  55
+            self.fields = field
  56
+
  57
+    def __iter__(self):
  58
+        for i, field in enumerate(self.fields):
  59
+            yield AdminField(self.form, field, is_first=(i == 0))
  60
+
  61
+    def errors(self):
  62
+        return mark_safe(u'\n'.join([self.form[f].errors.as_ul() for f in self.fields]).strip('\n'))
  63
+
  64
+class AdminField(object):
  65
+    def __init__(self, form, field, is_first):
  66
+        self.field = form[field] # A django.forms.BoundField instance
  67
+        self.is_first = is_first # Whether this field is first on the line
  68
+        self.is_checkbox = isinstance(self.field.field.widget, forms.CheckboxInput)
  69
+
  70
+    def label_tag(self):
  71
+        classes = []
  72
+        if self.is_checkbox:
  73
+            classes.append(u'vCheckboxLabel')
  74
+            contents = force_unicode(escape(self.field.label))
  75
+        else:
  76
+            contents = force_unicode(escape(self.field.label)) + u':'
  77
+        if self.field.field.required:
  78
+            classes.append(u'required')
  79
+        if not self.is_first:
  80
+            classes.append(u'inline')
  81
+        attrs = classes and {'class': u' '.join(classes)} or {}
  82
+        return self.field.label_tag(contents=contents, attrs=attrs)
  83
+
  84
+class InlineAdminFormSet(object):
  85
+    """
  86
+    A wrapper around an inline formset for use in the admin system.
  87
+    """
  88
+    def __init__(self, inline, formset, fieldsets):
  89
+        self.opts = inline
  90
+        self.formset = formset
  91
+        self.fieldsets = fieldsets
  92
+
  93
+    def __iter__(self):
  94
+        for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()):
  95
+            yield InlineAdminForm(self.formset, form, self.fieldsets, self.opts.prepopulated_fields, original)
  96
+        for form in self.formset.extra_forms:
  97
+            yield InlineAdminForm(self.formset, form, self.fieldsets, self.opts.prepopulated_fields, None)
  98
+
  99
+    def fields(self):
  100
+        for field_name in flatten_fieldsets(self.fieldsets):
  101
+            yield self.formset.form.base_fields[field_name]
  102
+
  103
+    def _media(self):
  104
+        media = self.opts.media + self.formset.media
  105
+        for fs in self:
  106
+            media = media + fs.media
  107
+        return media
  108
+    media = property(_media)
  109
+
  110
+class InlineAdminForm(AdminForm):
  111
+    """
  112
+    A wrapper around an inline form for use in the admin system.
  113
+    """
  114
+    def __init__(self, formset, form, fieldsets, prepopulated_fields, original):
  115
+        self.formset = formset
  116
+        self.original = original
  117
+        self.show_url = original and hasattr(original, 'get_absolute_url')
  118
+        super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields)
  119
+
  120
+    def pk_field(self):
  121
+        return AdminField(self.form, self.formset._pk_field_name, False)
  122
+
  123
+    def deletion_field(self):
  124
+        from django.forms.formsets import DELETION_FIELD_NAME
  125
+        return AdminField(self.form, DELETION_FIELD_NAME, False)
  126
+
  127
+    def ordering_field(self):
  128
+        from django.forms.formsets import ORDERING_FIELD_NAME
  129
+        return AdminField(self.form, ORDERING_FIELD_NAME, False)
  130
+
  131
+class AdminErrorList(forms.util.ErrorList):
  132
+    """
  133
+    Stores all errors for the form/formsets in an add/change stage view.
  134
+    """
  135
+    def __init__(self, form, inline_formsets):
  136
+        if form.is_bound:
  137
+            self.extend(form.errors.values())
  138
+            for inline_formset in inline_formsets:
  139
+                self.extend(inline_formset.non_form_errors())
  140
+                for errors_in_inline_form in inline_formset.errors:
  141
+                    self.extend(errors_in_inline_form.values())
162  django/contrib/admin/options.py
@@ -4,7 +4,8 @@
4 4
 from django.forms.models import BaseInlineFormSet
5 5
 from django.contrib.contenttypes.models import ContentType
6 6
 from django.contrib.admin import widgets
7  
-from django.contrib.admin.util import quote, unquote, get_deleted_objects
  7
+from django.contrib.admin import helpers
  8
+from django.contrib.admin.util import quote, unquote, flatten_fieldsets, get_deleted_objects
8 9
 from django.core.exceptions import PermissionDenied
9 10
 from django.db import models, transaction
10 11
 from django.http import Http404, HttpResponse, HttpResponseRedirect
@@ -26,94 +27,6 @@
26 27
 class IncorrectLookupParameters(Exception):
27 28
     pass
28 29
 
29  
-def flatten_fieldsets(fieldsets):
30  
-    """Returns a list of field names from an admin fieldsets structure."""
31  
-    field_names = []
32  
-    for name, opts in fieldsets:
33  
-        for field in opts['fields']:
34  
-            # type checking feels dirty, but it seems like the best way here
35  
-            if type(field) == tuple:
36  
-                field_names.extend(field)
37  
-            else:
38  
-                field_names.append(field)
39  
-    return field_names
40  
-
41  
-class AdminForm(object):
42  
-    def __init__(self, form, fieldsets, prepopulated_fields):
43  
-        self.form, self.fieldsets = form, fieldsets
44  
-        self.prepopulated_fields = [{
45  
-            'field': form[field_name],
46  
-            'dependencies': [form[f] for f in dependencies]
47  
-        } for field_name, dependencies in prepopulated_fields.items()]
48  
-
49  
-    def __iter__(self):
50  
-        for name, options in self.fieldsets:
51  
-            yield Fieldset(self.form, name, **options)
52  
-
53  
-    def first_field(self):
54  
-        for bf in self.form:
55  
-            return bf
56  
-
57  
-    def _media(self):
58  
-        media = self.form.media
59  
-        for fs in self:
60  
-            media = media + fs.media
61  
-        return media
62  
-    media = property(_media)
63  
-
64  
-class Fieldset(object):
65  
-    def __init__(self, form, name=None, fields=(), classes=(), description=None):
66  
-        self.form = form
67  
-        self.name, self.fields = name, fields
68  
-        self.classes = u' '.join(classes)
69  
-        self.description = description
70  
-
71  
-    def _media(self):
72  
-        from django.conf import settings
73  
-        if 'collapse' in self.classes:
74  
-            return forms.Media(js=['%sjs/admin/CollapsedFieldsets.js' % settings.ADMIN_MEDIA_PREFIX])
75  
-        return forms.Media()
76  
-    media = property(_media)
77  
-
78  
-    def __iter__(self):
79  
-        for field in self.fields:
80  
-            yield Fieldline(self.form, field)
81  
-
82  
-class Fieldline(object):
83  
-    def __init__(self, form, field):
84  
-        self.form = form # A django.forms.Form instance
85  
-        if isinstance(field, basestring):
86  
-            self.fields = [field]
87  
-        else:
88  
-            self.fields = field
89  
-
90  
-    def __iter__(self):
91  
-        for i, field in enumerate(self.fields):
92  
-            yield AdminField(self.form, field, is_first=(i == 0))
93  
-
94  
-    def errors(self):
95  
-        return mark_safe(u'\n'.join([self.form[f].errors.as_ul() for f in self.fields]).strip('\n'))
96  
-
97  
-class AdminField(object):
98  
-    def __init__(self, form, field, is_first):
99  
-        self.field = form[field] # A django.forms.BoundField instance
100  
-        self.is_first = is_first # Whether this field is first on the line
101  
-        self.is_checkbox = isinstance(self.field.field.widget, forms.CheckboxInput)
102  
-
103  
-    def label_tag(self):
104  
-        classes = []
105  
-        if self.is_checkbox:
106  
-            classes.append(u'vCheckboxLabel')
107  
-            contents = force_unicode(escape(self.field.label))
108  
-        else:
109  
-            contents = force_unicode(escape(self.field.label)) + u':'
110  
-        if self.field.field.required:
111  
-            classes.append(u'required')
112  
-        if not self.is_first:
113  
-            classes.append(u'inline')
114  
-        attrs = classes and {'class': u' '.join(classes)} or {}
115  
-        return self.field.label_tag(contents=contents, attrs=attrs)
116  
-
117 30
 class BaseModelAdmin(object):
118 31
     """Functionality common to both ModelAdmin and InlineAdmin."""
119 32
     raw_id_fields = ()
@@ -587,13 +500,13 @@ def add_view(self, request, form_url='', extra_context=None):
587 500
                 formset = FormSet(instance=self.model())
588 501
                 formsets.append(formset)
589 502
 
590  
-        adminForm = AdminForm(form, list(self.get_fieldsets(request)), self.prepopulated_fields)
  503
+        adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)), self.prepopulated_fields)
591 504
         media = self.media + adminForm.media
592 505
 
593 506
         inline_admin_formsets = []
594 507
         for inline, formset in zip(self.inline_instances, formsets):
595 508
             fieldsets = list(inline.get_fieldsets(request))
596  
-            inline_admin_formset = InlineAdminFormSet(inline, formset, fieldsets)
  509
+            inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets)
597 510
             inline_admin_formsets.append(inline_admin_formset)
598 511
             media = media + inline_admin_formset.media
599 512
 
@@ -604,7 +517,7 @@ def add_view(self, request, form_url='', extra_context=None):
604 517
             'show_delete': False,
605 518
             'media': mark_safe(media),
606 519
             'inline_admin_formsets': inline_admin_formsets,
607  
-            'errors': AdminErrorList(form, formsets),
  520
+            'errors': helpers.AdminErrorList(form, formsets),
608 521
             'root_path': self.admin_site.root_path,
609 522
         }
610 523
         context.update(extra_context or {})
@@ -664,13 +577,13 @@ def change_view(self, request, object_id, extra_context=None):
664 577
                 formset = FormSet(instance=obj)
665 578
                 formsets.append(formset)
666 579
 
667  
-        adminForm = AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields)
  580
+        adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields)
668 581
         media = self.media + adminForm.media
669 582
 
670 583
         inline_admin_formsets = []
671 584
         for inline, formset in zip(self.inline_instances, formsets):
672 585
             fieldsets = list(inline.get_fieldsets(request, obj))
673  
-            inline_admin_formset = InlineAdminFormSet(inline, formset, fieldsets)
  586
+            inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets)
674 587
             inline_admin_formsets.append(inline_admin_formset)
675 588
             media = media + inline_admin_formset.media
676 589
 
@@ -682,7 +595,7 @@ def change_view(self, request, object_id, extra_context=None):
682 595
             'is_popup': request.REQUEST.has_key('_popup'),
683 596
             'media': mark_safe(media),
684 597
             'inline_admin_formsets': inline_admin_formsets,
685  
-            'errors': AdminErrorList(form, formsets),
  598
+            'errors': helpers.AdminErrorList(form, formsets),
686 599
             'root_path': self.admin_site.root_path,
687 600
         }
688 601
         context.update(extra_context or {})
@@ -868,62 +781,3 @@ class StackedInline(InlineModelAdmin):
868 781
 
869 782
 class TabularInline(InlineModelAdmin):
870 783
     template = 'admin/edit_inline/tabular.html'
871  
-
872  
-class InlineAdminFormSet(object):
873  
-    """
874  
-    A wrapper around an inline formset for use in the admin system.
875  
-    """
876  
-    def __init__(self, inline, formset, fieldsets):
877  
-        self.opts = inline
878  
-        self.formset = formset
879  
-        self.fieldsets = fieldsets
880  
-
881  
-    def __iter__(self):
882  
-        for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()):
883  
-            yield InlineAdminForm(self.formset, form, self.fieldsets, self.opts.prepopulated_fields, original)
884  
-        for form in self.formset.extra_forms:
885  
-            yield InlineAdminForm(self.formset, form, self.fieldsets, self.opts.prepopulated_fields, None)
886  
-
887  
-    def fields(self):
888  
-        for field_name in flatten_fieldsets(self.fieldsets):
889  
-            yield self.formset.form.base_fields[field_name]
890  
-
891  
-    def _media(self):
892  
-        media = self.opts.media + self.formset.media
893  
-        for fs in self:
894  
-            media = media + fs.media
895  
-        return media
896  
-    media = property(_media)
897  
-
898  
-class InlineAdminForm(AdminForm):
899  
-    """
900  
-    A wrapper around an inline form for use in the admin system.
901  
-    """
902  
-    def __init__(self, formset, form, fieldsets, prepopulated_fields, original):
903  
-        self.formset = formset
904  
-        self.original = original
905  
-        self.show_url = original and hasattr(original, 'get_absolute_url')
906  
-        super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields)
907  
-
908  
-    def pk_field(self):
909  
-        return AdminField(self.form, self.formset._pk_field_name, False)
910  
-
911  
-    def deletion_field(self):
912  
-        from django.forms.formsets import DELETION_FIELD_NAME
913  
-        return AdminField(self.form, DELETION_FIELD_NAME, False)
914  
-
915  
-    def ordering_field(self):
916  
-        from django.forms.formsets import ORDERING_FIELD_NAME
917  
-        return AdminField(self.form, ORDERING_FIELD_NAME, False)
918  
-
919  
-class AdminErrorList(forms.util.ErrorList):
920  
-    """
921  
-    Stores all errors for the form/formsets in an add/change stage view.
922  
-    """
923  
-    def __init__(self, form, inline_formsets):
924  
-        if form.is_bound:
925  
-            self.extend(form.errors.values())
926  
-            for inline_formset in inline_formsets:
927  
-                self.extend(inline_formset.non_form_errors())
928  
-                for errors_in_inline_form in inline_formset.errors:
929  
-                    self.extend(errors_in_inline_form.values())
12  django/contrib/admin/util.py
@@ -43,6 +43,18 @@ def unquote(s):
43 43
             myappend('_' + item)
44 44
     return "".join(res)
45 45
 
  46
+def flatten_fieldsets(fieldsets):
  47
+    """Returns a list of field names from an admin fieldsets structure."""
  48
+    field_names = []
  49
+    for name, opts in fieldsets:
  50
+        for field in opts['fields']:
  51
+            # type checking feels dirty, but it seems like the best way here
  52
+            if type(field) == tuple:
  53
+                field_names.extend(field)
  54
+            else:
  55
+                field_names.append(field)
  56
+    return field_names
  57
+
46 58
 def _nest_help(obj, depth, val):
47 59
     current = obj
48 60
     for i in range(depth):

0 notes on commit 62aafd8

Please sign in to comment.
Something went wrong with that request. Please try again.