Optimization django admin panel queries with select_related and prefetch_related

These are my django models (only the FK s are written)

class SellerBuyable(TimeStampMixin, GBSoftDeleteModel):
    seller = models.ForeignKey(Seller,related_name="seller_buyables",on_delete=models.CASCADE, null=True)
    buyable = models.ForeignKey(Buyable,on_delete=models.CASCADE,null=True,related_name="seller_buyables",related_query_name='seller_buyable')
...
class CampaignItem(TimeStampMixin, GBSoftDeleteModel):
    campaign = models.ForeignKey(Campaign, related_name='items', on_delete=models.CASCADE)
    item = models.ForeignKey(SellerBuyable, on_delete=models.CASCADE, null=False)
    ...
class Campaign(TimeStampMixin, GBSoftDeleteModel):
    name = models.CharField()
    ... (has no FK)

And these are my codes in admin panel:

class CampaignItemStackedInline(SortableStackedInline):
    model = CampaignItem
    extra = 0
    ....

@admin.register(Campaign)
class CampaignAdmin(SortableAdminMixin, admin.ModelAdmin):
    inlines = [CampaignItemStackedInline]
    ...

A sample campaign had 11 items. When I open it's page, silk showed 84 queries.

I have simplified them to 40 queries by writing CampaignItemStackedInline like this:

class CampaignItemStackedInline(SortableStackedInline):
    model = CampaignItem
    extra = 0

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        qs = qs.select_related("campaign", "item__seller", "item__buyable")
        return qs

But I still have 3 queries for each "campaign inline item". 1 for Seller table, 1 for buyable and 1 for seller_buyable. I've tried prefetch_related in CampaignAdmin. The last version is this:

@admin.register(Campaign)
class CampaignAdmin(SortableAdminMixin, admin.ModelAdmin):
    ...
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        qs = qs.prefetch_related(
            Prefetch("items", queryset=CampaignItem.objects.select_related("item__seller", "item__buyable"))
        )
        return qs

But it only adds 1 prefetch query and turns into 41 queries

Hope to send enough info.

Вернуться на верх