Django DRF запросы, кажется, перезапускается, когда занимает много времени - PullRequest
0 голосов
/ 26 ноября 2018

Я использую Django с DRF, и у меня есть viewset, который записывает информацию в файл csv, а затем отправляет ссылку пользователю.

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

Проблема в том, что запрос занимает больше времени.Кажется, он просто перезапускается из запроса вызова сам по себе

    def get_operations(self, request):
        logger.info("Starting export request...")
   #[...business logic to retrive the data ...]
        file_url = settings.MEDIA_PREFIX_PATH + file_path
        logger.info("Saving response in %s", file_absolute_path)
        f = open(file_absolute_path, "w+")
        all_operations = operations.all()
        i = 0
        for operation in all_operations:
            i = i + 1
            #code to show progress in the log
            if (i / len(all_operations)*1000) % 5 == 0:
                logger.info("Progress:  %d ", (i / len(all_operations)*100))

            f.write("%s,%d,%d,%d,%s,%s\n" % (operation.datetime, operation.amount, operation.field2, operation.field3, operation.field5, operation.field6))
        logger.info("Response saved, sending link %s", file_url)
        return Response(file_url)

В журнале, это то, что я получаю

INFO 2018-11-26 11:23:33,525 Starting export request...
INFO 2018-11-26 11:23:34,223 Response retrieved : 17010 records
INFO 2018-11-26 11:23:34,225 Saving response in /tmp/generated_csv/1543231414.2250094.csv
INFO 2018-11-26 11:23:42,825 Progress:  10 
INFO 2018-11-26 11:23:51,161 Progress:  20 
INFO 2018-11-26 11:23:59,072 Progress:  30 
INFO 2018-11-26 11:24:07,694 Starting export request...
INFO 2018-11-26 11:24:08,346 Response retrieved : 17010 records
INFO 2018-11-26 11:24:08,348 Saving response in /tmp/generated_csv/1543231448.3486001.csv
INFO 2018-11-26 11:24:16,653 Progress:  10 
INFO 2018-11-26 11:24:24,271 Progress:  20 
INFO 2018-11-26 11:24:32,248 Progress:  30 
INFO 2018-11-26 11:24:42,573 Starting export request...
INFO 2018-11-26 11:24:44,101 Response retrieved : 17010 records
INFO 2018-11-26 11:24:44,109 Saving response in /tmp/generated_csv/1543231484.1097722.csv
INFO 2018-11-26 11:24:55,092 Progress:  10 
INFO 2018-11-26 11:25:04,131 Progress:  20 
INFO 2018-11-26 11:25:11,242 Progress:  30 
INFO 2018-11-26 11:25:16,801 Starting export request...
INFO 2018-11-26 11:25:17,499 Response retrieved : 17010 records
INFO 2018-11-26 11:25:17,501 Saving response in /tmp/generated_csv/1543231517.5013359.csv

Я уверен, что проблемане со стороны клиента, потому что я тоже пробовал это с почтальоном.

Я просто не понимаю, что может вызвать запрос сам по себе.

Спасибо

1 Ответ

0 голосов
/ 26 ноября 2018

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

import threading 

...

def process_file(self, file_absolute_path, all_operations):
        f = open(file_absolute_path, "w+")
        i = 0
        for operation in all_operations:
            i = i + 1
            # it will be visible in your logger file, so you can see the progress
            if (i / len(all_operations)*1000) % 5 == 0:
                logger.info("Progress:  %d ", (i / len(all_operations)*100))
                f.write("%s,%d,%d,%d,%s,%s\n" % (operation.datetime, operation.amount, operation.field2, operation.field3, operation.field5, operation.field6))

def get_operations(self, request):
    logger.info("Starting export request...")
    all_operations = operations.all()
    file_url = settings.MEDIA_PREFIX_PATH + file_path
    t = threading.Thread(target=self.process_file,
                         args=(file_absolute_path, all_operations))
    t.start()
    logger.info("Saving response in %s", file_absolute_path)
    logger.info("Response saved, sending link %s", file_url)
    return Response(file_url)

Здесь я привел пример использования Python's Threading .Но вы также можете использовать Сельдерей для этой цели (и это лучшее решение).

...