J'ai un modèle Pick
qui, lorsque je sélectionne un enregistrement dans Django Admin, prend un certain temps (environ 20 secondes) pour récupérer l'enregistrement (il y en a environ 70k). Cependant, c'est rapide lorsque j'essaye de créer / sauvegarder un enregistrement. J'ai ajouté les index pour essayer d'accélérer la récupération, mais je ne sais pas vraiment ce que je devrais faire
class Pick (models.Model): team = models.ForeignKey(Team, on_delete=models.CASCADE, null=True, blank=True) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, db_index=True) contest_entry=models.ForeignKey(ContestEntry, on_delete=models.CASCADE, db_index=True) game_round=models.ForeignKey(GameRound, on_delete=models.CASCADE, db_index=True) objects = DataFrameManager() def __str__(self): return f'%s %s' % (self.contest_entry, self.game_round) class Meta: unique_together = ['user', 'contest_entry', 'game_round'] ordering = ['contest_entry','game_round','user','team'] index_together = [["user", "contest_entry", 'game_round'],] indexes = [ models.Index(fields=['user', 'contest_entry', 'game_round']), models.Index(fields=['game_round'], name='game_round_idx'), models.Index(fields=['contest_entry'], name='contest_entry_idx'), ] class PickAdmin(admin.ModelAdmin): model = Pick list_filter= ( ('user', RelatedDropdownFilter), ('contest_entry__contest', RelatedDropdownFilter), ('game_round', RelatedDropdownFilter) ) def get_queryset(self, request): return super().get_queryset(request).select_related('user','contest_entry','game_round') admin.site.register(Pick, PickAdmin)
Comment puis-je améliorer les performances ici?
3 Réponses :
Je suppose que ce qui prend si longtemps, c'est le rendu des listes déroulantes pour les champs ForeignKey
de votre modèle.
Je vous suggère de regarder les requêtes SQL qui sont effectuées, soit en installant la barre d'outils Django, soit en activant la journalisation dans votre serveur de base de données.
Ce n'est pas la page avec les listes déroulantes qui prend du temps. C'est lorsque je sélectionne ensuite un élément dans la liste restante disponible, par exemple, je pourrais appeler https://example.com/admin/contests/pick/1013/change
. Cette page n'a pas de filtres - c'est simplement la page de changement pour le modèle Pick
C'est ce que je veux dire. Les listes déroulantes sur la page de modification / détail où vous sélectionnez user, contest_entry et game_rounds. Django doit récupérer toutes les données, et même si la requête est rapide, le rendu des modèles prend du temps.
Vous pouvez améliorer les requêtes en utilisant select_related pour les clés étrangères https://docs.djangoproject.com/en/2.2/ref/models/querysets/#select-related
J'ai essayé d'ajouter ceci à l'administrateur comme indiqué dans la modification, mais c'est maintenant plus lent sur la page de détails correspondante
La clé spécifie le raw_id_fields
sur la classe admin. Le widget par défaut pour les relations de clé étrangère peut entraîner une surcharge importante pour la récupération et le rendu de toutes les options.
class PickAdmin(admin.ModelAdmin): model = Pick list_filter= ( ('user', RelatedDropdownFilter), ('contest_entry__contest', RelatedDropdownFilter), ('game_round', RelatedDropdownFilter) ) raw_id_fields = ('user', 'contest_entry', 'game_round',) def get_queryset(self, request): return super().get_queryset(request).select_related('user','contest_entry','game_round')