Рубрики
Без рубрики

Как добавить на основе подписки Дросселя к API Django

Расширение структуры Django REST на запросы API дроссельной заслонки на основе конкретных пользовательских ограничений. Tagged с Python, Django, SaaS, API.

Python был естественным выбором, когда я начал Socialsentiment.io . Он позволил мне использовать один и тот же язык как для алгоритмов машинного обучения, так и для веб -разработки. И я использовал Django ранее для других проектов. Django Rest Framework (DRF) – отличный пакет для быстрого и легкости расширения проекта Django, чтобы предложить API. Сегодня мы рассмотрим, как расширить свои возможности для поддержки пользовательской дросселирования на основе подписок пользователей.

Модель подписки

Сначала давайте определим нашу приложение Модель подписки и требования к дросселированию:

  • Бесплатный уровень, позволяющий несколько сотен запросов API в день
  • Низкий платный уровень, предлагающий несколько тысяч запросов в день
  • Более высокий уровень затрат, предлагающий неограниченные запросы
  • Все уровни ограничены 5 запросами в секунду

Это очень распространенный вариант использования для современного приложения SaaS.

Пользовательский класс дросселя

Одна замечательная вещь о Django Rest Framework заключается в том, что он включает в себя множество встроенных вариантов для аутентификации и дросселирования. Каждый из них может применяться во всем мире или к определенным конечным точкам. Если вы хотите какой -либо тип вариантов динамического дросселя, вам понадобится его расширить. К счастью, архитектура DRF позволяет вам переопределить практически любую ее часть.

Давайте начнем с написания пользовательского класса, который переопределяет DRF’s USERRATETHTLETLE :

from rest_framework.throttling import UserRateThrottle

class SubscriptionRateThrottle(UserRateThrottle):
    # Define a custom scope name to be referenced by DRF in settings.py
    scope = "subscription"

    def __init__(self):
        super().__init__()

    def allow_request(self, request, view):
        """
        Override rest_framework.throttling.SimpleRateThrottle.allow_request

        Check to see if the request should be throttled.

        On success calls `throttle_success`.
        On failure calls `throttle_failure`.
        """
        if request.user.is_staff:
            # No throttling
            return True

        if request.user.is_authenticated:
            user_daily_limit = get_user_daily_limit(request.user)
            if user_daily_limit:
                # Override the default from settings.py
                self.duration = 86400
                self.num_requests = user_daily_limit
            else:
                # No limit == unlimited plan
                return True

        # Original logic from the parent method...

        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()

        # Drop any requests from the history which have now passed the
        # throttle duration
        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()

То, что мы делаем,-это динамически поиск газеты с конкретным пользователем в ключевой момент, чтобы переопределить DRF по умолчанию из файла настроек. Определите метод get_user_daily_limit Чтобы посмотреть значение. Я настоятельно рекомендую использовать методы кэша Django, если они хранятся в базе данных для производительности.

Настройки

Далее давайте посмотрим, что требуется в настройки.py :

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [...],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated'
    ],
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.UserRateThrottle',
        'app.throttling.SubscriptionDailyRateThrottle'
    ],
    'DEFAULT_THROTTLE_RATES': {
        'user': '5/second',
        'subscription': '200/day'
    }
}

Здесь мы установили два типа дросселирования. Встроенный USERRATETHTLETLE будет обрабатывать глобальные 5 запросов в секунду. Он находит эту настройку в Default_throttle_rates с ключом Пользователь Анкет Наш пользовательский класс дроссельной заслонки также включен и по умолчанию на Подписка Значение, если пользовательская подписка не найдена. Конечно, приложение должно быть написано, чтобы этого никогда не произошло, но хорошо иметь план отступления, если пользователь не настроен должным образом.

Подписки

Как вы кодируете и моделируете свои подписки, зависит от вас. В моем случае я написал статические классы, которые определяют детали каждого уровня подписки. A Подписка Модель ссылается на пользователя с конкретным планом с такими деталями, как время начала, сведения о платежах и т. Д.

Хорошая вещь – Django и DRF не диктуйте, как вы проектируете подписки на пользователя. В любом случае вы выбираете моделировать, они справится, потому что вы можете настроить каждый аспект авторизации и дросселирования.

Вывод

До сих пор у меня есть только хорошие вещи, чтобы сказать о гибкости Django и DRF и настройках, которые они позволяют. Они приняли правильный подход, предлагая широкий спектр встроенных возможностей, позволяя разработчикам возможность легко расширить или переопределить их. Он отлично работает для socialsentent.io и Наши API Анкет Я хотел бы услышать, как другие добавили свои собственные функции в Django Rest Framework в комментариях ниже.

Оригинал: “https://dev.to/mattschwartz/how-to-add-subscription-based-throttling-to-a-django-api-28j0”