Django admin 中的查询优化问题

问题描述 投票:0回答:1

我发现当我尝试打开对象创建窗口FriendlyMatch时,需要花费很多时间。大约2分钟。通过django调试工具栏我发现有4300个SQL查询。这是我的模型:

class Player(models.Model):
    """Модель игрока"""

    user = models.ForeignKey(
        User, related_name="player", on_delete=models.CASCADE, verbose_name="Игрок"
    )
    created = models.DateTimeField(auto_now_add=True)
    team = models.ForeignKey(
        Team,
        related_name="team_player",
        null=True,
        on_delete=models.SET_NULL,
        verbose_name="Команда",
    )

    class Meta:
        """Мета класс модели Игрока"""

        verbose_name = "Игрок"
        verbose_name_plural = "Игроки"

    def __str__(self):
        return f"Игрок {self.user.username}"

class FriendlyMatch(models.Model):
    """Модель Дружеского матча"""

    date_start = models.DateTimeField(
        verbose_name="Дата и время начала", null=True, blank=True
    )
    date_end = models.DateTimeField(
        verbose_name="Дата и время окончания", null=True, blank=True
    )
    duration_macth = models.SmallIntegerField(
        verbose_name="Длительность дружеского матча", default=3, null=True, blank=True
    )
    creator = models.ForeignKey(
        User,
        related_name="creator_friendly_match",
        null=True,
        on_delete=models.SET_NULL,
        verbose_name="Создатель",
    )
    player_1 = models.ForeignKey(
        Player,
        related_name="friendly_match_player1",
        null=True,
        on_delete=models.SET_NULL,
        verbose_name="Игрок 1",
    )
    player_2 = models.ForeignKey(
        Player,
        related_name="friendly_match_player2",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name="Игрок 2",
    )
    first_game_winner = models.ForeignKey(
        Player,
        related_name="first_game_winner_friendly_match",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name="Победитель первой игры",
    )
    second_game_winner = models.ForeignKey(
        Player,
        related_name="second_game_winner_friendly_match",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name="Победитель второй игры",
    )
    third_game_winner = models.ForeignKey(
        Player,
        related_name="third_game_winner_friendly_match",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name="Победитель третьей игры",
    )
    fourth_game_winner = models.ForeignKey(
        Player,
        related_name="fourth_game_winner_friendly_match",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name="Победитель четвертой игры",
    )
    fifth_game_winner = models.ForeignKey(
        Player,
        related_name="fifth_game_winner_friendly_match",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name="Победитель пятой игры",
    )
    winner = models.ForeignKey(
        Player,
        related_name="friendly_match_winner_friendly_match",
        on_delete=models.CASCADE,
        verbose_name="Победитель",
        null=True,
        blank=True,
    )
    status_friendly_match = models.CharField(
        verbose_name="Статус дружеского матча",
        choices=StatusChoices.choices,
        max_length=64,
        default=StatusChoices.NOT_STARTED,
    )

    class Meta:
        """Мета класс для Дружеского матча"""

        verbose_name = "Дружеский матч"
        verbose_name_plural = "Дружеский матчи"

这是我的FriendlyMatch模型的管理模型:

@admin.register(FriendlyMatch)
class FriendlyMatchAdmin(admin.ModelAdmin):
    list_display = ("id", "date_start", "player_1", "player_2", "status_friendly_match")

在寻找解决方案时,发现这是受到相关模型的str方法的影响。我从 Player 模型中删除了 str 方法,然后查询数量减少,并且 SQL 查询一切都变得正常。如何在不从 Player 模型中删除 str 方法的情况下优化查询?

python-3.x django django-admin
1个回答
0
投票

您可以使用 list_select_lated 告诉 Django modeladmin 类使用 select_lated() 来检索管理更改列表页面上的对象列表。这可以为您节省大量数据库查询。

您还可以结合 only() 方法来指定要在查询集中检索的字段集。

@admin.register(FriendlyMatch)
class FriendlyMatchAdmin(admin.ModelAdmin):
    list_display = ("id", "date_start", "player_1", "player_2", "status_friendly_match")
    list_select_related = ["player_1", "player_2"]
    
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        qs = qs.only(
            "id", "date_start", "status_friendly_match", "player_1_id", "player_1__user", "player_2_id", "player_2__user"
        )
        return qs

如果您想在一次查询中显示玩家的用户名和数据检索。您可以使用下面的代码。

@admin.register(FriendlyMatch)
class FriendlyMatchAdmin(admin.ModelAdmin):
    list_display = ("id", "date_start", "player_1", "player_2", "status_friendly_match")
    list_select_related = ["player_1", "player_2", "player_1__user", "player_2__user"]

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        qs = qs.only(
            "id", "date_start", "status_friendly_match", "player_1_id", "player_1__user__username", "player_2_id", "player_2__user__username"
        )
        return qs
© www.soinside.com 2019 - 2024. All rights reserved.