如何从Django admin中删除所有重复和类似的查询

kgsdhlau  于 2023-04-07  发布在  Go
关注(0)|答案(1)|浏览(157)

我的项目中有很多不同的模型,每个模型都有重复的SQL查询
我想知道如何删除它们,但主要问题是,在一个模型中,当我试图查看该模型的单个对象时,我有5 k个SQL查询。
我还尝试在我的模板中循环所有来自这个模型的信息,仍然得到~ 5 k个查询,它是如何工作的?
models.py

class PresenceSectionList(models.Model):
    presence_detail = models.ForeignKey(PresenceDetailInfo, on_delete=models.CASCADE)
    presence_sections = models.ForeignKey(CleanSections, blank=True, on_delete=models.CASCADE, null=True)

    class Meta:
        verbose_name = 'Раздел с информацией'
        verbose_name_plural = 'Разделы с информацией'
        ordering = ['presence_detail', ]

    def __str__(self):
        return f'{self.presence_detail}'

class CleanSections(models.Model):
    GUID = models.UUIDField(default=uuid.uuid4, editable=True, unique=True)
    name = models.CharField(max_length=120, verbose_name='Краткое наименование')
    details = models.CharField(max_length=300, verbose_name='Описание', blank=True)

class ObjectList(models.Model):
    GUID = models.UUIDField(default=uuid.uuid4, editable=True, unique=True)
    name = models.CharField(max_length=250, verbose_name='Наименование')
    customer_guid = models.ForeignKey(CounterParty, related_name='customer_guid', on_delete=models.CASCADE,
                                      verbose_name='Наименование заказчика', default=None, blank=True, null=True)

    contractor_guid = models.ManyToManyField(CounterParty, related_name='contractor_guid',
                                             verbose_name='Наименование подрядчика', default=None, blank=True)

    sections = models.ManyToManyField('SectionList', default=None, related_name='section', verbose_name='Разделы',
                                      blank=True)

class CounterParty(models.Model):
    GUID = models.UUIDField(default=uuid.uuid4, editable=True, unique=True)
    name = models.CharField(max_length=150, verbose_name='Наименование')
    customer = models.BooleanField(default=False, verbose_name='Заказчик')
    contractor = models.BooleanField(default=False, verbose_name='Подрядчик')
    counter_user = models.ManyToManyField(User, blank=True, related_name='counter_user',
                                          verbose_name='Пользователи контрагента')

admin.py

class PresenceSectionListAdmin(admin.ModelAdmin):
    list_display = ('presence_detail', 'presence_sections')
    ordering = ['presence_detail__presence_info', 'presence_detail__work_date']

admin.site.register(PresenceSectionList, PresenceSectionListAdmin)

Number of SQL queries

6xfqseft

6xfqseft1#

当Django Admin加载一个PresenceSectionList对象列表时,它会访问两个属性:presence_detailpresence_sections。由于这些字段是关系,因此Django需要为每个PresenceSectionList获取一个PresenceDetailInfo和一个CleanSections对象
这是一种非常低效的方式。使用.select_related()QuerySet的方法会更好。这将在一个查询中获取主模型和相关模型。
在django admin中,你需要覆盖get_queryset()方法:
PresenceSectionListAdmin类中,添加:

def get_queryset(request):
    base_qs = super().get_queryset(request)
    return base_qs.select_related("presence_detail", "presence_sections")

这将减少查询的数量。
PS.我还可以在你的截图中看到很多重复的查询FROM common_counterpart,这是我在你的示例代码中看不到的。你可以尝试select_related或prefetch_related(如果是m2m关系)。

相关问题