Как подождать в django, пока придет запрос на конечную точку?

Подскажите, с помощью чего можно дождаться ответа на другой конечной точке? Я нахожусь на главной странице (index), ввожу что-то в форму. POST запрос отправляется на другой сервер. В этот момент:

  • другой сервер обрабатывает данные и, в зависимости от их правильности, делает POST-запрос к моему url /answer (True или False).
  • я буду перенаправлен, например, на другую страницу. Как зарегистрировать логику другой страницы (another) так, чтобы Django ждал POST-запрос с другого сервера к /answer и в зависимости от этого запроса True/False я выводил все OK или все Bad на этой странице?
url.py

urlpatterns = [
    path('index/', index, name='index'),
    path('page_2/', page_2, name='page_2'),
    path('answer/', answer, name='answer'),
]
-------------------------------------------------

views.py

def index(request):
    requests.post(example.com, data='My data')
    return redirect('page_2')

def page_2(request):
    # wait request in answer
    if request.session['answer'] is True:
        return 'Ok'
    retunr 'Bad'

def answer(request):
    data = request.data
    # send to page_2 or save in request.session['answer']
    return Response(status=200)

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

Однако для достижения этой цели нам необходим канал связи между index и answer представлением. Поэтому для реализации коммуникации следующим образом:

  • index: Привет answer! Я отправил запрос. Я собираюсь спать, разбуди меня, если ты получил результат.
  • .
  • answer: О, я понял. Вот ты где. Просыпайся!
  • index: Спасибо. Теперь я обработаю его и верну свой ответ.

Таким образом, этот канал может быть чем угодно! Модель в базе данных, несколько сущностей в redis, несколько файлов в файловой системе и т.д.

Одним из возможных решений с использованием моделей может быть следующее:

  • Создайте модель (назовите ее, например, ExampleRequest), состоящую из булевого поля received
  • .
  • В представлении index создайте экземпляр ExampleRequest с received = False перед отправкой запроса.
  • В представлении answer найдите ранее созданный ExampleRequest и установите его поле received в значение True
  • .
  • В представлении index после отправки запроса в цикле while сделайте запрос к базе данных и проверьте, есть ли у созданного экземпляра ExampleRequest received = True? Если да, то внешний сервер вызвал answer. Поэтому прервите цикл while и выполните остальную работу; в противном случае просто time.sleep(1) и продолжите цикл while.

Обратите внимание:

  • Когда несколько клиентов используют ваш сайт, некоторые из них могут запросить index представление, и тогда будет более одного экземпляра ExampleRequest. В представлении answer вы должны иметь возможность определить, к какому из этих экземпляров относится текущий запрос. Возможно, вам понадобится хранить уникальные данные, относящиеся к этому запросу, в модели ExampleRequest.
  • Вы можете рассмотреть ситуацию, когда другой сервер не вызывает answer view никогда. Поэтому может существовать верхняя граница для итераций цикла while цикла index представления.
  • Также вы можете удалить ExampleRequest экземпляры после их захвата в index представлении, чтобы оптимизировать использование диска вашей базы данных.

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

Это, возможно, не полный ответ, но он дает вам путь.

def index(request):
    requests.post(example.com, data='My data')
    return redirect('page_2')

Измените его на следующий

import httpx
async def index(request):
   async with httpx.AsyncClient() as client:
      response = await client.post(example.com, data='My data')
      print(response.json())
Вернуться на верх