Even synchronous implementations handle usually multiple requests 'in parallel'.
They do so by using multiple processes, multiple threads or a mix of it.
Depending on the server they have a predefined (fixed) amount of processes or threads or they dynamically allocate threads or processes whenever another requests requires one.
An asynchronous server on the other hand can handle multiple requests 'in parallel' within only one thread / process.
The simple development server, that you can start with management.py runserver
is using threading by default.
To best visualize this I suggest to change your code to:
import time
import os
import threading
@action(detail=False, methods=['get'])
def test(self, request):
print("START PID", os.getpid(), "TID", threading.get_native_id())
time.sleep(5)
print("STOP PID", os.getpid(), "TID", threading.get_native_id())
return {pid=os.getpid(), tid=threading.get_native_id()}
As @xyres mentioned: There is a command line option to disable threading.
Just run manage.py runserver --nothreading
and try again. Now you should be able to visualize the full synchronous behavior.