[DRF] Extrait pour accélérer PrimaryKeyRelatedField

introduction

Si vous définissez PrimaryKeyRelatedField sur many = True dans le sérialiseur, vous pouvez passer un tableau de pk comme paramètre de requête, mais ce sera très lent s'il y a beaucoup de pk. Par conséquent, j'ai enquêté sur la cause et réfléchi à la manière de l'accélérer.

Cause

Conclusion c'est

ManyRelatedField.py


def to_internal_value(self, data):
    if isinstance(data, str) or not hasattr(data, '__iter__'):
        self.fail('not_a_list', input_type=type(data).__name__)
    if not self.allow_empty and len(data) == 0:
        self.fail('empty')

    return [
        self.child_relation.to_internal_value(item)
        for item in data
    ]

C'était lent car le tableau self.child_relation.to_internal_value (item) a été appelé (obtenant pk in to_internal_value)

Extraits pour accélérer

from rest_framework import serializers
from rest_framework.relations import MANY_RELATION_KWARGS, ManyRelatedField


class PrimaryKeyRelatedFieldEx(serializers.PrimaryKeyRelatedField):
    def __init__(self, **kwargs):
        self.queryset_response = kwargs.pop('queryset_response', False)
        super().__init__(**kwargs)

    class _ManyRelatedFieldEx(ManyRelatedField):
        def to_internal_value(self, data):
            if isinstance(data, str) or not hasattr(data, '__iter__'):
                self.fail('not_a_list', input_type=type(data).__name__)
            if not self.allow_empty and len(data) == 0:
                self.fail('empty')
            return self.child_relation.to_internal_value(data)

    @classmethod
    def many_init(cls, *args, **kwargs):
        list_kwargs = {'child_relation': cls(*args, **kwargs)}
        for key in kwargs:
            if key in MANY_RELATION_KWARGS:
                list_kwargs[key] = kwargs[key]
        return cls._ManyRelatedFieldEx(**list_kwargs)

    def to_internal_value(self, data):
        if isinstance(data, list):
            if self.pk_field is not None:
                data = self.pk_field.to_internal_value(data)
            results = self.get_queryset().filter(pk__in=data)
            #Vérifiez si toutes les données sont disponibles
            pk_list = results.values_list('pk', flat=True)
            pk_list = [str(n) for n in pk_list]
            data_list = [str(n) for n in data]
            diff = list(set(data_list) - set(list(pk_list)))
            if len(diff) > 0:
                pk_value = ', '.join(map(str, diff))
                self.fail('does_not_exist', pk_value=pk_value)
            if self.queryset_response:
                return results
            else:
                return list(results)
        else:
            return super().to_internal_value(data)

Commentaire

Recommended Posts

[DRF] Extrait pour accélérer PrimaryKeyRelatedField
Numba pour accélérer en Python
Projet Euler 4 Tentative d'accélération
Comment accélérer les calculs Python
Comment accélérer la belle instanciation de soupe
Comment accélérer Scicit-Learn comme Conda Numpy
[Python] Faites de votre mieux pour accélérer SQL Alchemy
Essais et erreurs pour accélérer la génération de cartes thermiques
Essai et erreur pour accélérer les captures d'écran Android
Tous jusqu'à 775/664, 777/666, 755/644, etc.
Ce que j'ai fait pour accélérer la tâche de recherche de chaînes
J'ai essayé d'accélérer la création vidéo en traitant en parallèle
Mongodb Shortest Introduction (3) J'ai essayé d'accélérer même des millions
Accélérez la commande netstat
N'écrivez pas Python si vous voulez l'accélérer avec Python
[Python] Hit Keras depuis TensorFlow et TensorFlow depuis c ++ pour accélérer l'exécution.
Indispensable si vous utilisez Python! Comment utiliser Numpy pour accélérer les calculs!