Caching model choice fields in admin inlines.

728 views
Skip to first unread message

Sean Brant

unread,
May 23, 2011, 11:29:52 AM5/23/11
to Django developers
If you have ever used a inline in the admin for a model that contained
a model choice field you have probably noticed it has to query the
database for each row to fill the select drop-down. This results in n+
identical queries.

I though it might be useful to have a way to tell a admin inline to
cache the choices of fields. Here is some rough code that gets the job
done::


from django.forms.models import BaseInlineFormSet


class CachedInlineFormSet(BaseInlineFormSet):
cached_fields = []

def _construct_form(self, i, **kwargs):
form = super(CachedInlineFormSet, self)._construct_form(i,
**kwargs)
for cache_field in self.cached_fields:
field = form.fields[cache_field]
field.cache_choices = True
choices = getattr(self, '_cached_%s_choices' %
cache_field, None)
if choices is None:
choices = list(field.choices)
setattr(self, '_cached_%s_choices' % cache_field,
choices)
field.choice_cache = choices
return form


class CachedTabularInline(admin.TabularInline):
cached_fields = []

def get_formset(self, request, obj=None, **kwargs):
formset = super(CachedTabularInline,
self).get_formset(request, obj=None, **kwargs)
formset.cached_fields = self.cached_fields
return formset


class MyInline(CachedTabularInline):
model = MyModel
cache_fields = ['myfk']


Im not super big on how this patches the classes in various places so
i'm open to better suggestions. Is this something that the admin could
benefit from or is this better kept as a 3rd party tool?

andybak

unread,
May 25, 2011, 2:19:34 PM5/25/11
to Django developers
I seem to recall a similar problem rears it's ugly head on editable
changelists too.

And obviously it's potentially worse there as n can often be larger.

Vimukthi

unread,
Jul 7, 2011, 1:02:08 AM7/7/11
to Django developers
I have a formset in my application where there is a select field and
also a multiselect field in a form. In some object edit view, number
of times each form in the formset gets called increases with the
increase of number of relationships between objects in the db(see my
question on stackoverflow -
http://stackoverflow.com/questions/6591890/django-formsets-slow-on-many-to-many-relationships).
Because of the way formsets work this means the number of queries to
the db also increase and it causes an unacceptable latency in the
view. Although caching is required in the case of multiple requests
for the same view, I think the first improvement that should be made
is to have the repeated form as a property of formset object(in the
first time it gets instantiated) and then use that property as
required. Do you see any problems with this?
Reply all
Reply to author
Forward
0 new messages