Lazy Load Django Admin Inlines

2.1k views Asked by At

I have a model with as many as 20 fields. It is also referenced as ManytoMany in another model which references it using a through table. Let me put a scenario here showing my case.

class Class1(models.Model):
  some_field = .....
  myfield1 = models.ManyToManyField(Class2,through='Another')
  ......

class Another(models.Model):
   class1 = models.ForeignKey(Class1, related_name='class1_class2')
   class2 = models.ForeignKey(Class2, related_name='class1_class2')

"Another" is an admin inline field, using default Admin UI of Django. The problem is that if there are too many objects of "Another" which loads lot of other objects of class1 and class2, NGINX gives me 502: Bad Gateway.

I am not willing to increase the NGINX time, I have already done that many times. What I want to know is that, if there is a way I can say Django Admin to load the inlines only after all other contents are loaded, or say Lazy Load the inlines.

I have gone through almost every post that says Lazy Loading in Django, but it all applies to a particular view or a field, I found nothing close to what I need.

I would be very appreciable if anyone can shed some light on this.

Regards.

1

There are 1 answers

0
Justin Gourley On

Using defer may give you what you need...

https://docs.djangoproject.com/en/dev/ref/models/querysets/#defer

defer

defer(*fields) In some complex data-modeling situations, your models might contain a lot of fields, some of which could contain a lot of data (for example, text fields), or require expensive processing to convert them to Python objects. If you are using the results of a queryset in some situation where you don’t know if you need those particular fields when you initially fetch the data, you can tell Django not to retrieve them from the database.

This is done by passing the names of the fields to not load to defer():

Entry.objects.defer("headline", "body") A queryset that has deferred fields will still return model instances. Each deferred field will be retrieved from the database if you access that field (one at a time, not all the deferred fields at once).

You can make multiple calls to defer(). Each call adds new fields to the deferred set:

Defers both the body and headline fields.

Entry.objects.defer("body").filter(rating=5).defer("headline") The order in which fields are added to the deferred set does not matter. Calling defer() with a field name that has already been deferred is harmless (the field will still be deferred).

You can defer loading of fields in related models (if the related models are loading via select_related()) by using the standard double-underscore notation to separate related fields:

Blog.objects.select_related().defer("entry__headline", "entry__body") If you want to clear the set of deferred fields, pass None as a parameter to defer():

Load all fields immediately.

my_queryset.defer(None) Some fields in a model won’t be deferred, even if you ask for them. You can never defer the loading of the primary key. If you are using select_related() to retrieve related models, you shouldn’t defer the loading of the field that connects from the primary model to the related one, doing so will result in an error.