Как подождать в 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 сделайте запрос к базе данных и проверьте, есть ли у созданного экземпляраExampleRequestreceived = True? Если да, то внешний сервер вызвалanswer. Поэтому прервите цикл while и выполните остальную работу; в противном случае простоtime.sleep(1)и продолжите цикл while.
Обратите внимание:
- Когда несколько клиентов используют ваш сайт, некоторые из них могут запросить
indexпредставление, и тогда будет более одного экземпляраExampleRequest. В представленииanswerвы должны иметь возможность определить, к какому из этих экземпляров относится текущий запрос. Возможно, вам понадобится хранить уникальные данные, относящиеся к этому запросу, в моделиExampleRequest. - Вы можете рассмотреть ситуацию, когда другой сервер не вызывает
answerview никогда. Поэтому может существовать верхняя граница для итераций цикла 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())