diff -r 2d5cd6f1136e django/contrib/admin/options.py
|
a
|
b
|
|
| 830 | 830 | formset = FormSet(request.POST, request.FILES, |
| 831 | 831 | instance=new_object, prefix=prefix) |
| 832 | 832 | formsets.append(formset) |
| | 833 | for inline in self.inline_instances: |
| | 834 | # If this is the inline that matches this formset, and |
| | 835 | # we have some nested inlines to deal with, then we need |
| | 836 | # to get the relevant formset for each of the forms in |
| | 837 | # the current formset. |
| | 838 | if inline.inlines and inline.model == formset.model: |
| | 839 | for nested in inline.inline_instances: |
| | 840 | for the_form in formset.forms: |
| | 841 | InlineFormSet = nested.get_formset(request, the_form.instance) |
| | 842 | prefix = "%s-%s" % (the_form.prefix, InlineFormSet.get_default_prefix()) |
| | 843 | formsets.append(InlineFormSet(request.POST, request.FILES, instance=the_form.instance, prefix=prefix)) |
| 833 | 844 | |
| 834 | 845 | if all_valid(formsets) and form_validated: |
| 835 | 846 | self.save_model(request, new_object, form, change=True) |
| … |
… |
|
| 859 | 870 | for inline, formset in zip(self.inline_instances, formsets): |
| 860 | 871 | fieldsets = list(inline.get_fieldsets(request, obj)) |
| 861 | 872 | inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets) |
| | 873 | if inline.inlines: |
| | 874 | for form in formset.forms: |
| | 875 | if form.instance.pk: |
| | 876 | instance = form.instance |
| | 877 | else: |
| | 878 | instance = None |
| | 879 | form.inlines = inline.get_inlines(request, instance, prefix=form.prefix) |
| | 880 | inline_admin_formset.inlines = inline.get_inlines(request) |
| 862 | 881 | inline_admin_formsets.append(inline_admin_formset) |
| 863 | 882 | media = media + inline_admin_formset.media |
| 864 | 883 | |
| … |
… |
|
| 1119 | 1138 | template = None |
| 1120 | 1139 | verbose_name = None |
| 1121 | 1140 | verbose_name_plural = None |
| | 1141 | inlines = [] |
| 1122 | 1142 | |
| 1123 | 1143 | def __init__(self, parent_model, admin_site): |
| 1124 | 1144 | self.admin_site = admin_site |
| … |
… |
|
| 1129 | 1149 | self.verbose_name = self.model._meta.verbose_name |
| 1130 | 1150 | if self.verbose_name_plural is None: |
| 1131 | 1151 | self.verbose_name_plural = self.model._meta.verbose_name_plural |
| | 1152 | self.inline_instances = [] |
| | 1153 | for inline_class in self.inlines: |
| | 1154 | inline_instance = inline_class(self.model, self.admin_site) |
| | 1155 | self.inline_instances.append(inline_instance) |
| 1132 | 1156 | |
| 1133 | 1157 | def _media(self): |
| 1134 | 1158 | from django.conf import settings |
| … |
… |
|
| 1171 | 1195 | form = self.get_formset(request).form |
| 1172 | 1196 | return [(None, {'fields': form.base_fields.keys()})] |
| 1173 | 1197 | |
| | 1198 | def get_inlines(self, request, obj=None, prefix=None): |
| | 1199 | nested_inlines = [] |
| | 1200 | for inline in self.inline_instances: |
| | 1201 | FormSet = inline.get_formset(request, obj) |
| | 1202 | prefix = "%s-%s" % (prefix, FormSet.get_default_prefix()) |
| | 1203 | formset = FormSet(instance=obj, prefix=prefix) |
| | 1204 | fieldsets = list(inline.get_fieldsets(request, obj)) |
| | 1205 | nested_inline = helpers.InlineAdminFormSet(inline, formset, fieldsets) |
| | 1206 | nested_inlines.append(nested_inline) |
| | 1207 | return nested_inlines |
| | 1208 | |
| | 1209 | |
| 1174 | 1210 | class StackedInline(InlineModelAdmin): |
| 1175 | 1211 | template = 'admin/edit_inline/stacked.html' |
| 1176 | 1212 | |
diff -r 2d5cd6f1136e django/contrib/admin/templates/admin/edit_inline/nested.html
|
-
|
+
|
|
| | 1 | <td> |
| | 2 | {{ nested.formset.management_form }} |
| | 3 | <table> |
| | 4 | <thead> |
| | 5 | <tr> |
| | 6 | {% for field in nested.fields %} |
| | 7 | <th {% if forloop.first %}colspan="2"{% endif %}>{{ field.label|capfirst }}</th> |
| | 8 | {% endfor %} |
| | 9 | {% if nested.formset.can_delete %} |
| | 10 | <th>Delete?</th> |
| | 11 | {% endif %} |
| | 12 | </tr> |
| | 13 | </thead> |
| | 14 | |
| | 15 | <tbody> |
| | 16 | {% for formset in nested %} |
| | 17 | {% if formset.form.non_field_errors %} |
| | 18 | <tr><td colspan="{{ formset.field_count }}"> |
| | 19 | {{ form.form.non_field_errors }} |
| | 20 | </td></tr> |
| | 21 | {% endif %} |
| | 22 | <tr class="{% if formset.original %}has_original{% endif %}"> |
| | 23 | <td class="original"> |
| | 24 | {% if formset.original %}<p style="position:relative;"> |
| | 25 | {{ formset.original }} |
| | 26 | </p>{% endif %} |
| | 27 | {% if formset.has_auto_field %} |
| | 28 | {{ formset.pk_field.field }} |
| | 29 | {% endif %}{{ formset.fk_field.field }} |
| | 30 | </td> |
| | 31 | {% for fieldset in formset %} |
| | 32 | {% for line in fieldset %} |
| | 33 | {% for field in line %} |
| | 34 | <td class="{{ field.field.name }}"> |
| | 35 | {{ field.field.errors.as_ul}} |
| | 36 | {{ field.field }} |
| | 37 | </td> |
| | 38 | {% endfor %} |
| | 39 | {% endfor %} |
| | 40 | {% endfor %} |
| | 41 | {% if formset.original and nested.formset.can_delete %} |
| | 42 | <td class="delete">{{ formset.deletion_field.field }}</td> |
| | 43 | {% endif %} |
| | 44 | </tr> |
| | 45 | {% endfor %} |
| | 46 | </tbody> |
| | 47 | </table> |
| | 48 | </td> |
| | 49 | No newline at end of file |
diff -r 2d5cd6f1136e django/contrib/admin/templates/admin/edit_inline/tabular.html
|
a
|
b
|
|
| 13 | 13 | {% endif %} |
| 14 | 14 | {% endfor %} |
| 15 | 15 | {% if inline_admin_formset.formset.can_delete %}<th>{% trans "Delete?" %}</th>{% endif %} |
| | 16 | {% if inline_admin_formset.inlines %} |
| | 17 | {% for nested in inline_admin_formset.inlines %} |
| | 18 | <th>{{ nested.opts.verbose_name_plural|capfirst }}</th> |
| | 19 | {% endfor %} |
| | 20 | {% endif %} |
| 16 | 21 | </tr></thead> |
| 17 | 22 | |
| 18 | 23 | <tbody> |
| … |
… |
|
| 21 | 26 | <tr><td colspan="{{ inline_admin_form.field_count }}">{{ inline_admin_form.form.non_field_errors }}</td></tr> |
| 22 | 27 | {% endif %} |
| 23 | 28 | <tr class="{% cycle row1,row2 %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}"> |
| 24 | | |
| | 29 | |
| 25 | 30 | <td class="original"> |
| 26 | 31 | {% if inline_admin_form.original or inline_admin_form.show_url %}<p> |
| 27 | 32 | {% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %} |
| … |
… |
|
| 54 | 59 | {% if inline_admin_formset.formset.can_delete %} |
| 55 | 60 | <td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td> |
| 56 | 61 | {% endif %} |
| 57 | | |
| | 62 | |
| | 63 | {% if inline_admin_formset.inlines %} |
| | 64 | {% for nested in inline_admin_form.form.inlines %} |
| | 65 | {% include 'admin/edit_inline/nested.html' %} |
| | 66 | {% endfor %} |
| | 67 | {% endif %} |
| 58 | 68 | </tr> |
| 59 | | |
| 60 | 69 | {% endfor %} |
| 61 | 70 | </tbody> |
| 62 | 71 | </table> |
diff -r 2d5cd6f1136e django/contrib/admin/validation.py
|
a
|
b
|
|
| 177 | 177 | raise ImproperlyConfigured("%s cannot exclude the field " |
| 178 | 178 | "'%s' - this is the foreign key to the parent model " |
| 179 | 179 | "%s." % (cls.__name__, fk.name, parent_model.__name__)) |
| | 180 | |
| | 181 | # nested inlines |
| | 182 | # inlines = [] |
| | 183 | if hasattr(cls, 'inlines'): |
| | 184 | check_isseq(cls, 'inlines', cls.inlines) |
| | 185 | for idx, inline in enumerate(cls.inlines): |
| | 186 | if not issubclass(inline, BaseModelAdmin): |
| | 187 | raise ImproperlyConfigured("'%s.inlines[%d]' does not inherit" |
| | 188 | " from BaseModelAdmin." % (cls.__name__, idx)) |
| | 189 | if not inline.model: |
| | 190 | raise ImproperlyConfigured("'model' is a required attribute " |
| | 191 | "of '%s.inlines[%d]'." % (cls.__name__, idx)) |
| | 192 | if not issubclass(inline.model, models.Model): |
| | 193 | raise ImproperlyConfigured("'%s.inlines[%s].model' does not " |
| | 194 | "inherit from models.Model." % (cls.__name__, idx)) |
| | 195 | validate_base(inline, inline.model) |
| | 196 | validate_inline(inline, cls, cls.model) |
| 180 | 197 | |
| 181 | 198 | def validate_base(cls, model): |
| 182 | 199 | opts = model._meta |