Почему второй декоратор вызывается дважды?

Ссылка скопирована
1 ответ

У меня есть два декоратора.

@csrf_exempt @RateLimitMiddleware def add_user(r):     if r.method == "POST":         if r.headers.get("Token") == Token:             data_dict = json.loads(r.body)             answer = VerificationCodes.send_code(data_dict.get('email'),                                                  data_dict.get('username'), data_dict.get('password'))             return HttpResponse(json.dumps(answer[0]), status=answer[1])         else:             return HttpResponse("<h1>I don't know who you are!</h1>", status=401)     else:         return HttpResponse("<h1>You picked the wrong method, fool!</h1>", status=405)

@csrf_exempt @RateLimitMiddleware def add_user(r): if r.method == "POST": if r.headers.get("Token") == Token: data_dict = json.loads(r.body) answer = VerificationCodes.send_code(data_dict.get('email'), data_dict.get('username'), data_dict.get('password')) return HttpResponse(json.dumps(answer[0]), status=answer[1]) else: return HttpResponse("<h1>I don't know who you are!</h1>", status=401) else: return HttpResponse("<h1>You picked the wrong method, fool!</h1>", status=405)

В таком порядке второй декоратор вызывается дважды, не знаю ,почему. Если их поменять местами, то не срабатывает отключение проверки CSRF. Код мидлваря приложил ниже. Раньше работало нормально, а щас через пень колоду.

class RateLimitMiddleware:     def __init__(self, get_response):         self.get_response = get_response      def __call__(self, request):         ip_address = request.META.get('REMOTE_ADDR')         key = f'ratelimit_{ip_address}'          if cache.get(key):             return HttpResponse("Too many requests", status=429)          cache.set(key, 1, 2)  # Задаем таймаут в секундах          response = self.get_response(request)         return response

class RateLimitMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): ip_address = request.META.get('REMOTE_ADDR') key = f'ratelimit_{ip_address}' if cache.get(key): return HttpResponse("Too many requests", status=429) cache.set(key, 1, 2) # Задаем таймаут в секундах response = self.get_response(request) return response

Дополнительно:

Я сам нашел ответ случайным образом. Дело оказалось в том, что я зарегистрировал этот класс в settings.py как мидлварь, и в придачу записал как декоратор перед нужной мне функцией. Вследствие этого этот класс использовался и как мидлварь для всех запросов, и как декоратор для той функции, поэтому вызывался дважды. Я убрал запись как мидлваря из settings.py и теперь всё работает

  • Я сам нашел ответ случайным образом.

    ага, случайно, я тебе это явно написал

  • Everything_is_bad, Неа. Я знаю, что мидлвари туда записываются, у меня он там записан был. Я уже объяснил, как это вышло

Ответы:

поди стандартно, не два раза вызывается, а твой браузер еще и favicon запросил, в итоге тебе сразу два запроса прилетело, смотри логи

  • Я не через браузере, а через Postman запросы кидаю. Раньше такого не было, опять же. Это API я делаю
  • Юра Милевский, еще раз, посмотри логи, может тебе сначала OPTIONS прилетает, потом запрос, а для API вообще лучше сразу DRF использовать, чтобы не писать кучу своих велосипедов
  • Everything_is_bad, я смотрел DRF. Там с ходу начали рассказывать про сериализаторы. Я код не особо понял(вообще не понял), но по смыслу я понял, что мне это не нужно, ибо необходимый словарь я сам собираю. В качестве этой фичи с антидудосом запросами мне скинули Throttling из DRF, но и его я чёт не понял. Анонимный рейт, юзер рейт. Код какой-то непонятный. Слишком сложно чёт для меня.
  • Everything_is_bad, А ещё по поводу тегов. Я тег питон не зря поставил. Я тему с мидлварями и декораторами не изучал, и в другом месте мне сказали, что это вещи разные, поэтому я решил на всякий случай добавить и такой тег.
  • Юра Милевский, о кстати, слона и не заметил, с чего ты решил что надо делать @RateLimitMiddleware? middleware в настройках settings,py прописываются, ты доки вообще читаешь? https://docs.djangoproject.com/en/5.0/topics/http/...
  • Everything_is_bad, Да, я знаю. Я вспомнил, что ещё раньше закомментил не зря. Мне ведь надо было накатывать не на все запрос, а лишь на конкретные, поэтому я использовал декоратор и убрал мидлварь из настроек. А щас я вернулся к этому и тупанул)
Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Елена Вебер Ответ

Проблема с вызовом второго декоратора дважды может возникнуть из-за неправильной структуры вашего кода или неправильного использования декораторов.

При использовании декораторов важно помнить, что каждый декоратор должен вызывать следующий декоратор в цепочке. Если второй декоратор вызывается дважды, это может быть вызвано неправильным порядком вызова декораторов или неправильным использованием метода super().

Например, давайте рассмотрим следующий пример кода на PHP с двумя декораторами:

class FirstDecorator {
    protected $component;
 
    public function __construct(Component $component) {
        $this->component = $component;
    }
 
    public function operation() {
        // do something before calling the next decorator
        $this->component->operation();
        // do something after calling the next decorator
    }
}
 
class SecondDecorator {
    protected $component;
 
    public function __construct(Component $component) {
        $this->component = $component;
    }
 
    public function operation() {
        // do something before calling the next decorator
        $this->component->operation();
        // do something after calling the next decorator
    }
}
 
// Пример использования декораторов
$component = new ConcreteComponent();
$decorator1 = new FirstDecorator($component);
$decorator2 = new SecondDecorator($decorator1);
 
$decorator2->operation();

class FirstDecorator { protected $component; public function __construct(Component $component) { $this->component = $component; } public function operation() { // do something before calling the next decorator $this->component->operation(); // do something after calling the next decorator } } class SecondDecorator { protected $component; public function __construct(Component $component) { $this->component = $component; } public function operation() { // do something before calling the next decorator $this->component->operation(); // do something after calling the next decorator } } // Пример использования декораторов $component = new ConcreteComponent(); $decorator1 = new FirstDecorator($component); $decorator2 = new SecondDecorator($decorator1); $decorator2->operation();

В данном примере, если второй декоратор вызывается дважды, возможно, что вы забыли вызвать метод $this->component->operation() внутри метода operation() в первом декораторе. Убедитесь, что каждый декоратор правильно вызывает следующий декоратор в цепочке.

Также, удостоверьтесь, что вы правильно передаете предыдущий декоратор в конструкторе следующего декоратора, чтобы создать правильную цепочку декораторов.

Если проблема с вызовом второго декоратора дважды сохраняется, пожалуйста, предоставьте больше информации о вашем коде, чтобы мы могли более точно определить причину проблемы и предложить более конкретное решение.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно