0

Tell me with what you can wait for a response to another endpoint? I am on the main page (index), entering something into the form. The POST request is sent to another server. At this moment:

  • another server processes the data and, depending on their correctness, makes a POST request to my url /answer (True or False).
  • I will be redirected, for example, to another page. How to register the logic of another page (another) so that Django waits for a POST request from another server to /answer and depending on this request True/False, I output everything OK or everything Bad on this page?
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)

2 Answers 2

1

I reckon it's a strange situation and it's better if you could redesign the logic of your code so that the view functions process the request ASAP and not busily wait for external events to be triggered as it increases response time.

However, in order to achieve this purpose we need a communication channel between index and answer view. So to implement a communication like this:

  • index: Hey answer! I've sent the request. I'm going to sleep, wake me up if you got its result.
  • answer: Oh I got it man. Here you are. Wake up!
  • index: Thanks. Now I process it and return my response.

So this channel might be anything! A model in database, some entities in redis, some files in filesystem, etc.

One possible solution using the models might be:

  • Create a model(name it ExampleRequest for example) consisting of a boolean field named received
  • In index view, create an instance of ExampleRequest with received = False before sending the request.
  • In answer view, find the previously created ExampleRequest and set its received field to True
  • In index view, after sending the request, in a while loop, query the database and check if the created ExampleRequest instance has received = True? If yes, then the external server has called answer. So break the while and do the rest of the work; otherwise, just time.sleep(1) and continue the while loop.

Just note:

  • When multiple clients are using your website, some of them might request index view and then there will be more than one instance of ExampleRequest. In answer view, you have to be able to find out the current request is related to which one of those instances. You might need to store a unique data related to that request in ExampleRequest model.
  • You might consider the situation where the other server doesn't call answer view ever. So there might be an upper bound for the iterations of index view's while loop.
  • Also you may remove ExampleRequest instances after capturing them in index view in order to optimize disk usage of your database.

I say it again, it's better if you can do the polling stuff in frontend instead of backend to avoid high response time and other syncing issues.

0

This might not the complete answer, but it gives you way.

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

Change it to following

import httpx
async def index(request):
   async with httpx.AsyncClient() as client:
      response = await client.post(example.com, data='My data')
      print(response.json())

Not the answer you're looking for? Browse other questions tagged or ask your own question.