Skip to content

Instantly share code, notes, and snippets.

@razum2um
Created July 4, 2011 21:47
Show Gist options
  • Save razum2um/1063986 to your computer and use it in GitHub Desktop.
Save razum2um/1063986 to your computer and use it in GitHub Desktop.
django nested sets (level<=3) support
From bbb53d927c0949246c1735baaf34aa4261cfbb3c Mon Sep 17 00:00:00 2001
From: Vlad Bokov <razum2um@mail.ru>
Date: Tue, 5 Jul 2011 04:14:42 +0700
Subject: [PATCH] nested sets (level<=3) support
---
django/contrib/admin/options.py | 36 +++++++++++++++
.../admin/templates/admin/edit_inline/nested.html | 48 ++++++++++++++++++++
.../admin/templates/admin/edit_inline/tabular.html | 13 +++++-
3 files changed, 96 insertions(+), 1 deletions(-)
create mode 100644 django/contrib/admin/templates/admin/edit_inline/nested.html
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 550f46a..8dad2f2 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -937,6 +937,17 @@ class ModelAdmin(BaseModelAdmin):
formset = FormSet(instance=self.model(), prefix=prefix,
queryset=inline.queryset(request))
formsets.append(formset)
+ for inline in self.inline_instances:
+ # If this is the inline that matches this formset, and
+ # we have some nested inlines to deal with, then we need
+ # to get the relevant formset for each of the forms in
+ # the current formset.
+ if inline.inlines and inline.model == formset.model:
+ for nested in inline.inline_instances:
+ for the_form in formset.forms:
+ InlineFormSet = nested.get_formset(request, the_form.instance)
+ prefix = "%s-%s" % (the_form.prefix, InlineFormSet.get_default_prefix())
+ formsets.append(InlineFormSet(request.POST, request.FILES, instance=the_form.instance, prefix=prefix))
adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)),
self.get_prepopulated_fields(request),
@@ -1041,6 +1052,14 @@ class ModelAdmin(BaseModelAdmin):
prepopulated = dict(inline.get_prepopulated_fields(request, obj))
inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
fieldsets, prepopulated, readonly, model_admin=self)
+ if inline.inlines:
+ for form in formset.forms:
+ if form.instance.pk:
+ instance = form.instance
+ else:
+ instance = None
+ form.inlines = inline.get_inlines(request, instance, prefix=form.prefix)
+ inline_admin_formset.inlines = inline.get_inlines(request)
inline_admin_formsets.append(inline_admin_formset)
media = media + inline_admin_formset.media
@@ -1315,6 +1334,7 @@ class InlineModelAdmin(BaseModelAdmin):
verbose_name = None
verbose_name_plural = None
can_delete = True
+ inlines = []
def __init__(self, parent_model, admin_site):
self.admin_site = admin_site
@@ -1325,6 +1345,10 @@ class InlineModelAdmin(BaseModelAdmin):
self.verbose_name = self.model._meta.verbose_name
if self.verbose_name_plural is None:
self.verbose_name_plural = self.model._meta.verbose_name_plural
+ self.inline_instances = []
+ for inline_class in self.inlines:
+ inline_instance = inline_class(self.model, self.admin_site)
+ self.inline_instances.append(inline_instance)
def _media(self):
js = ['jquery.min.js', 'jquery.init.js', 'inlines.min.js']
@@ -1370,6 +1394,18 @@ class InlineModelAdmin(BaseModelAdmin):
fields = form.base_fields.keys() + list(self.get_readonly_fields(request, obj))
return [(None, {'fields': fields})]
+ def get_inlines(self, request, obj=None, prefix=None):
+ nested_inlines = []
+ for inline in self.inline_instances:
+ FormSet = inline.get_formset(request, obj)
+ prefix = "%s-%s" % (prefix, FormSet.get_default_prefix())
+ formset = FormSet(instance=obj, prefix=prefix)
+ fieldsets = list(inline.get_fieldsets(request, obj))
+ nested_inline = helpers.InlineAdminFormSet(inline, formset, fieldsets)
+ nested_inlines.append(nested_inline)
+ return nested_inlines
+
+
class StackedInline(InlineModelAdmin):
template = 'admin/edit_inline/stacked.html'
diff --git a/django/contrib/admin/templates/admin/edit_inline/nested.html b/django/contrib/admin/templates/admin/edit_inline/nested.html
new file mode 100644
index 0000000..a8d4b74
--- /dev/null
+++ b/django/contrib/admin/templates/admin/edit_inline/nested.html
@@ -0,0 +1,48 @@
+<td>
+ {{ nested.formset.management_form }}
+ <table>
+ <thead>
+ <tr>
+ {% for field in nested.fields %}
+ <th {% if forloop.first %}colspan="2"{% endif %}>{{ field.label|capfirst }}</th>
+ {% endfor %}
+ {% if nested.formset.can_delete %}
+ <th>Delete?</th>
+ {% endif %}
+ </tr>
+ </thead>
+
+ <tbody>
+ {% for formset in nested %}
+ {% if formset.form.non_field_errors %}
+ <tr><td colspan="{{ formset.field_count }}">
+ {{ form.form.non_field_errors }}
+ </td></tr>
+ {% endif %}
+ <tr class="{% if formset.original %}has_original{% endif %}">
+ <td class="original">
+ {% if formset.original %}<p style="position:relative;">
+ {{ formset.original }}
+ </p>{% endif %}
+ {% if formset.has_auto_field %}
+ {{ formset.pk_field.field }}
+ {% endif %}{{ formset.fk_field.field }}
+ </td>
+ {% for fieldset in formset %}
+ {% for line in fieldset %}
+ {% for field in line %}
+ <td class="{{ field.field.name }}">
+ {{ field.field.errors.as_ul}}
+ {{ field.field }}
+ </td>
+ {% endfor %}
+ {% endfor %}
+ {% endfor %}
+ {% if formset.original and nested.formset.can_delete %}
+ <td class="delete">{{ formset.deletion_field.field }}</td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+</td>
\ No newline at end of file
diff --git a/django/contrib/admin/templates/admin/edit_inline/tabular.html b/django/contrib/admin/templates/admin/edit_inline/tabular.html
index 8294227..bef900e 100644
--- a/django/contrib/admin/templates/admin/edit_inline/tabular.html
+++ b/django/contrib/admin/templates/admin/edit_inline/tabular.html
@@ -13,8 +13,12 @@
{% endif %}
{% endfor %}
{% if inline_admin_formset.formset.can_delete %}<th>{% trans "Delete?" %}</th>{% endif %}
+ {% if inline_admin_formset.inlines %}
+ {% for nested in inline_admin_formset.inlines %}
+ <th>{{ nested.opts.verbose_name_plural|capfirst }}</th>
+ {% endfor %}
+ {% endif %}
</tr></thead>
-
<tbody>
{% for inline_admin_form in inline_admin_formset %}
{% if inline_admin_form.form.non_field_errors %}
@@ -22,6 +26,7 @@
{% endif %}
<tr class="{% cycle "row1" "row2" %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}{% if forloop.last %} empty-form{% endif %}"
id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
+
<td class="original">
{% if inline_admin_form.original or inline_admin_form.show_url %}<p>
{% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
@@ -56,6 +61,12 @@
{% if inline_admin_formset.formset.can_delete %}
<td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
{% endif %}
+
+ {% if inline_admin_formset.inlines %}
+ {% for nested in inline_admin_form.form.inlines %}
+ {% include 'admin/edit_inline/nested.html' %}
+ {% endfor %}
+ {% endif %}
</tr>
{% endfor %}
</tbody>
--
1.7.3.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment