I'm trying to use Django admin to visualize all samples in one request. It works, but it is really slow. I tried to use prefetch
, formset
, raw_id_fields
, and readonly_fields
with no luck. It is still very slow when I load more than 10 samples. I'm having a N+1 problem here. I checked on Django debug toolbar and it makes a query for each sample in that request.
Here are my models:
# This is where the sample has all information
class Inventory(models.Model):
sample_id = models.CharField(max_length=50, primary_key=True)
def __str__(self):
return '{0}'.format(self.sample_id)
# Intermediate model
class SampleRequestInventory(models.Model):
sample = models.ForeignKey("Inventory", on_delete=models.CASCADE)
request = models.ForeignKey("SampleRequest", on_delete=models.CASCADE)
# This is the request model that I'm looking
class SampleRequest(models.Model):
samples = models.ManyToManyField("Inventory", through="SampleRequestInventory")
Here are my django admin configuration:
class SamplesInline(admin.TabularInline):
model = SampleRequestInventory
# raw_id_fields = ('sample',)
readonly_fields = ('sample',)
extra = 0
# this formset did not work either
# class MyInlineFormset(BaseInlineFormSet):
# def __init__(self, data=None, files=None, instance=None,
# save_as_new=False, prefix=None, queryset=None, **kwargs):
# super(MyInlineFormset, self).__init__(data, files, instance,
# save_as_new, prefix, queryset, **kwargs)
# self.queryset = SampleRequest.objects.all(). \
# prefetch_related('samples')
class SampleRequestAdmin(admin.ModelAdmin):
# This queryset for prefetching only makes an extra query...
def get_queryset(self, request):
qs = super(SampleRequestAdmin, self).get_queryset(request)
return qs.prefetch_related('samples')
# extra settings
list_display = ('date', 'status',)
ordering = ('date',)
# inline that causes the slowness
inlines = (SamplesInline, )
# I tried using formset as well, but didn't work
# formset = MyInlineFormset
Try adding the following to your SamplesInline:
def get_queryset(self, request):
qs = super(SamplesInline, self).get_queryset(request)
return qs.select_related('sample')
The readonly_fields
in your Inline is causing the extra lookup to satisfy the __str__
for your Inventory
class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With