django-nested-admin icon indicating copy to clipboard operation
django-nested-admin copied to clipboard

Bad performance with nested polymorphic models

Open ADR-007 opened this issue 5 years ago • 2 comments

Hi! First of all, I have to say that I am really happy I found this plugin!

I used a polymorphic model that related to another polymorphic model. I total I have 5 polymorphic types on the first level and 3 on the second one. It produces about 26 000 lines of HTML code and takes 5 seconds to render it.

There is a pretty simple solution to reduce the rendering time by using caching:

In templates/nesting/admin/inlines/polymorphic_stacked.html change this:

                {% if inline_admin_form.form.inlines %}
                  {% for nested in inline_admin_form.form.inlines %}
                    {% include nested.opts.template with inline_admin_formset=nested %}
                  {% endfor %}
                {% endif %}

to this:

              {% if inline_admin_form.is_empty and inline_admin_form.form.inlines %}
                {% with inline_admin_formset.opts|to_class_name as formset_class_name %}
                  {% cache 600 repeated-nested-template formset_class_name %}
                    {% if inline_admin_form.form.inlines %}
                      {% for nested in inline_admin_form.form.inlines %}
                        {% include nested.opts.template with inline_admin_formset=nested %}
                      {% endfor %}
                    {% endif %}
                  {% endcache %}
                {% endwith %}
              {% else %}
                {% if inline_admin_form.form.inlines %}
                  {% for nested in inline_admin_form.form.inlines %}
                    {% include nested.opts.template with inline_admin_formset=nested %}
                  {% endfor %}
                {% endif %}
              {% endif %}

and this this to the top of the file:

{% load cache %}
{% load adminextras %}

templatetags/adminextras.py:

from django import template


register = template.Library()


@register.filter
def to_class_name(value):
    return value.__class__.__name__

It reduces rendering time from 5 to 2 seconds.

Currently, I don't have enough time to prepare PR with tests but hope this snippet will be helpful for someone.

ADR-007 avatar Feb 12 '20 16:02 ADR-007

This is a brilliant idea. I think I'll probably put it behind a setting and disable it by default, but this will help us as well with performance.

fdintino avatar Feb 13 '20 15:02 fdintino

This turns out to be not as straightforward as I would have hoped. There are more variables involved than just formset_class_name that would need to vary the cache.

fdintino avatar Jun 01 '20 04:06 fdintino