Почему второй декоратор вызывается дважды?
У меня есть два декоратора.
@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, Да, я знаю. Я вспомнил, что ещё раньше закомментил не зря. Мне ведь надо было накатывать не на все запрос, а лишь на конкретные, поэтому я использовал декоратор и убрал мидлварь из настроек. А щас я вернулся к этому и тупанул)
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Проблема с вызовом второго декоратора дважды может возникнуть из-за неправильной структуры вашего кода или неправильного использования декораторов.
При использовании декораторов важно помнить, что каждый декоратор должен вызывать следующий декоратор в цепочке. Если второй декоратор вызывается дважды, это может быть вызвано неправильным порядком вызова декораторов или неправильным использованием метода 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();
В данном примере, если второй декоратор вызывается дважды, возможно, что вы забыли вызвать метод $this->component->operation() внутри метода operation() в первом декораторе. Убедитесь, что каждый декоратор правильно вызывает следующий декоратор в цепочке.
Также, удостоверьтесь, что вы правильно передаете предыдущий декоратор в конструкторе следующего декоратора, чтобы создать правильную цепочку декораторов.
Если проблема с вызовом второго декоратора дважды сохраняется, пожалуйста, предоставьте больше информации о вашем коде, чтобы мы могли более точно определить причину проблемы и предложить более конкретное решение.