Création de classes de limitation de fréquence personnalisées, analyse du code source des fréquences, pagination, tri et filtrage

  1. Classe de limitation de fréquence personnalisée

Pour créer votre propre classe de limitation, héritez de BaseThrottle et implémentez la méthode allow_request. Sinon, une erreur sera levée.

from rest_framework.throttling import BaseThrottle, SimpleRateThrottle

class CustomThrottle(SimpleRateThrottle):
    scope = 'my_scope'

    def get_cache_key(self, request, view):
        # Utilise l'adresse IP comme clé de cache
        return request.META.get('REMOTE_ADDR')

class UserThrottle(BaseThrottle):
    dump = {}  # Dictionnaire partagé pour stocker l'historique

    def __init__(self):
        self.history = None

    def allow_request(self, request, view):
        ip = request.META.get('REMOTE_ADDR')
        import time
        now = time.time()
        if ip not in self.dump:
            self.dump[ip] = [now]
            return True
        self.history = self.dump[ip]
        # Supprime les entrées plus anciennes que 60 secondes
        while self.history and now - self.history[-1] > 60:
            self.history.pop()
        if len(self.history) < 3:  # Limite à 3 requêtes par minute
            self.history.insert(0, now)
            return True
        return False

  1. Analyse du code source des fréquences

Le moteur de DRF utilise la méthode allow_request de la classe de limitation. Voici le foncsionnement de SimpleRateThrottle :

# SimpleRateThrottle (extrait du code source)
class SimpleRateThrottle(BaseThrottle):
    cache = default_cache
    timer = time.time
    cache_format = 'throttle_%(scope)s_%(ident)s'
    scope = None
    THROTTLE_RATES = api_settings.DEFAULT_THROTTLE_RATES

    def __init__(self):
        # Lors de l'instanciation, self.rate est défini via get_rate()
        if not getattr(self, 'rate', None):
            self.rate = self.get_rate()  # Retourne par ex. '3/m'
        # num_requests et duration sont extraits de la chaîne
        self.num_requests, self.duration = self.parse_rate(self.rate)

    def get_rate(self):
        # Récupère le taux depuis la configuration
        return self.THROTTLE_RATES[self.scope]

    def parse_rate(self, rate):
        if rate is None:
            return (None, None)
        num, period = rate.split('/')
        num_requests = int(num)
        duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
        return (num_requests, duration)

    def allow_request(self, request, view):
        if self.rate is None:
            return True
        self.key = self.get_cache_key(request, view)
        if self.key is None:
            return True
        self.history = self.cache.get(self.key, [])
        self.now = self.timer()
        # Nettoie les entrées expirées
        while self.history and self.history[-1] <= self.now - self.duration:
            self.history.pop()
        if len(self.history) >= self.num_requests:
            return self.throttle_failure()
        return self.throttle_success()

# Résumé : Pour créer une classe de limitation personnalisée, il suffit d'hériter de SimpleRateThrottle,
# de redéfinir get_cache_key, de définir l'attribut scope et de configurer THROTTLE_RATES dans settings.

  1. Pagination

DRF propose trois types de pagination :

from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination

class CustomPageNumberPagination(PageNumberPagination):
    page_size = 2               # Éléments par page
    page_query_param = 'page'   # Paramètre de requête pour le numéro de page
    page_size_query_param = 'size'   # Paramètre optionnel pour définir la taille
    max_page_size = 5           # Taille maximale autorisée

class CustomLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 3
    limit_query_param = 'limit'    # Nombre d'éléments affichés
    offset_query_param = 'offset'  # Index de départ
    max_limit = 5

class CustomCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'
    page_size = 2
    ordering = '-id'   # Tri par défaut (décroissant sur id)

  1. Tri et filtarge

Utilisez OrderingFilter pour le tri et SearchFilter pour la recherche textuelle :

from rest_framework.filters import OrderingFilter, SearchFilter

class MaVue(viewsets.ModelViewSet):
    queryset = MonModele.objects.all()
    serializer_class = MonSerializer
    filter_backends = [SearchFilter, OrderingFilter]
    search_fields = ['name']          # Champs sur lesquels faire une recherche
    ordering_fields = ['id']          # Champs autorisés pour le tri

4.1 Filtrage avancé avec django‑filters

from django_filters.rest_framework.backends import DjangoFilterBackend

class MaVue(viewsets.ModelViewSet):
    queryset = MonModele.objects.all()
    serializer_class = MonSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['id']         # Champs sur lesquels filtrer exactement

Étiquettes: DRF limitation de fréquence Pagination tri filtre

Publié le 7 juin à 19h23