Ticket #9025: nested_inlines.diff

File nested_inlines.diff, 8.4 KB (added by Matthew Schinckel, 15 years ago)

Alternate patch: against trunk

  • django/contrib/admin/options.py

    diff -r 2d5cd6f1136e django/contrib/admin/options.py
    a b  
    830830                formset = FormSet(request.POST, request.FILES,
    831831                                  instance=new_object, prefix=prefix)
    832832                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))
    833844
    834845            if all_valid(formsets) and form_validated:
    835846                self.save_model(request, new_object, form, change=True)
     
    859870        for inline, formset in zip(self.inline_instances, formsets):
    860871            fieldsets = list(inline.get_fieldsets(request, obj))
    861872            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)
    862881            inline_admin_formsets.append(inline_admin_formset)
    863882            media = media + inline_admin_formset.media
    864883
     
    11191138    template = None
    11201139    verbose_name = None
    11211140    verbose_name_plural = None
     1141    inlines = []
    11221142
    11231143    def __init__(self, parent_model, admin_site):
    11241144        self.admin_site = admin_site
     
    11291149            self.verbose_name = self.model._meta.verbose_name
    11301150        if self.verbose_name_plural is None:
    11311151            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)
    11321156
    11331157    def _media(self):
    11341158        from django.conf import settings
     
    11711195        form = self.get_formset(request).form
    11721196        return [(None, {'fields': form.base_fields.keys()})]
    11731197
     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
    11741210class StackedInline(InlineModelAdmin):
    11751211    template = 'admin/edit_inline/stacked.html'
    11761212
  • new file django/contrib/admin/templates/admin/edit_inline/nested.html

    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
  • django/contrib/admin/templates/admin/edit_inline/tabular.html

    diff -r 2d5cd6f1136e django/contrib/admin/templates/admin/edit_inline/tabular.html
    a b  
    1313        {% endif %}
    1414     {% endfor %}
    1515     {% 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 %}
    1621     </tr></thead>
    1722
    1823     <tbody>
     
    2126        <tr><td colspan="{{ inline_admin_form.field_count }}">{{ inline_admin_form.form.non_field_errors }}</td></tr>
    2227        {% endif %}
    2328        <tr class="{% cycle row1,row2 %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}">
    24 
     29         
    2530        <td class="original">
    2631          {% if inline_admin_form.original or inline_admin_form.show_url %}<p>
    2732          {% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
     
    5459        {% if inline_admin_formset.formset.can_delete %}
    5560          <td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
    5661        {% 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 %}
    5868        </tr>
    59 
    6069     {% endfor %}
    6170     </tbody>
    6271   </table>
  • django/contrib/admin/validation.py

    diff -r 2d5cd6f1136e django/contrib/admin/validation.py
    a b  
    177177            raise ImproperlyConfigured("%s cannot exclude the field "
    178178                    "'%s' - this is the foreign key to the parent model "
    179179                    "%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)
    180197
    181198def validate_base(cls, model):
    182199    opts = model._meta
Back to Top