Django - Как делать вызовы API через постоянные интервалы - PullRequest
0 голосов
/ 09 мая 2018

Что я хочу сделать: Я создал панель мониторинга, которая отображает ключевые показатели эффективности, которые я получаю от API на Zendesk.com. Он должен обновляться через регулярные промежутки времени (я пытаюсь использовать time.sleep () для достижения этой цели), но это не может происходить слишком часто, поскольку у меня ограничение в 700 запросов в минуту. Я использовал Django, чтобы создать интерфейс для отображения данных. ЭТО НИКОГДА НЕ ИСПОЛЬЗУЕТСЯ КАК ВЕБ-САЙТ.

Проблема: Я использую jquery "get" вызовы, чтобы получить данные из моего скрипта. Если я использую «python manage.py runserver», это, в конечном итоге, создаст, как мне кажется, очень много рабочих, и слишком часто будет делать вызовы к моему сценарию и превысит мой предел в 700 запросов с Zendesk. Если я использую "python manage.py runserver --nothreading", он прекрасно работает ОДНАКО, когда я нажимаю кнопку на панели навигации или пытаюсь обновить страницу, мне нужно дождаться полного запуска скрипта, прежде чем он перейдет к задаче.

Соответствующий код моей программы:

Например, в HTML-коде я вызываю данные из json:

     <script type="text/javascript">
         $(document).ready(function() {
           function pollSiteData () {
           $.get('/nb_new/', function(resp) {
             $('#nb_new').text(resp['nb_new']);
           });
           window.setTimeout(pollSiteData,10000);
           }
           pollSiteData();
           });
     </script>

Какие вызовы в представлении на основе классов:

url(r'^nb_new/',views.SiteNumberView.as_view())

Представление выглядит следующим образом (xxxxxx - это моя учетная информация для тестирования):

class SiteNumberView(views.APIView):
    def get(self, request, *args, **kwargs):
        data = engine.main("xxxxx","xxxxxx","xxxxxx")
        return JsonResponse(data)

Приведенное выше представление на основе классов вызывает функцию "main" из файла engine.py, который я создал.

Функция:

def main(*args):
    client = ZenClient(args)
    time.sleep(45)
    print("Next iteration")
    return get_infos(client, "open", "pending", "new")

вызов функции main get_infos, который возвращает диктонар, который я конвертирую в json.

def get_infos(client, status, status2, status3):

    #Script that downloads stats from Zendesk

    return {"nb_new": str(len(filtered_new_tickets))}

Когда я запускаю "python manage.py runserver", мы видим, что он использует мой скрипт слишком часто:

Next iteration
Next iteration
Next iteration
[09/May/2018 08:01:21] "GET /nb_new/ HTTP/1.1" 200 86
Next iteration
[09/May/2018 08:01:30] "GET /nb_new/ HTTP/1.1" 200 86
Next iteration
[09/May/2018 08:01:35] "GET /nb_new/ HTTP/1.1" 200 86
Next iteration
[09/May/2018 08:01:51] "GET /nb_new/ HTTP/1.1" 200 86
[09/May/2018 08:02:04] "GET /nb_new/ HTTP/1.1" 200 86
Next iteration

Когда я использую "python manage.py runserver --nothreading", он делает вызовы с хорошими интервалами, но кнопки на интерфейсе не реагируют. (Я полагаю, потому что он должен завершить сценарий, прежде чем он сможет подтвердить нажатие кнопки.)

Вот изображение моего интерфейса («nb_new» обновляет количество заявок рядом с «ответом на запрос поддержки»)

Interface

Вывод / вопрос: Как я могу убедиться, что мой скрипт работает только, скажем, раз в минуту и ​​15 секунд, но все же позволить интерфейсу реагировать на нажатие кнопки или обновление страницы? Пожалуйста, постарайтесь не давать решений, которые потребовали бы от меня использования совершенно другой основы. К сожалению, время - очень скудный ресурс.

1 Ответ

0 голосов
/ 09 мая 2018

Вот простое решение:

  1. Создание отдельного скрипта Python, предназначенного для ping API Zendesk через равные промежутки времени. Когда поступают новые данные, они помещают данные в очередь или базу данных.
  2. Создайте представление Django, которое будет отвечать на ваши вызовы jQuery. Он считывает данные из базы данных или очереди и возвращает их в запрос jQuery. На самом деле он не будет запрашивать сам API Zendesk.

Более простым способом хранения новых обновлений будет создание выделенной модели только для этих данных. Создайте один экземпляр этой модели и просто продолжайте обновлять его состояние (значения полей) всякий раз, когда поступают новые данные, вместо того, чтобы каждый раз создавать отдельный объект. Затем, по вашему мнению, всякий раз, когда вы получаете вызов jQuery, вы можете вернуть этот объект.

Если вам не нравится этот подход «модель и база данных», вы можете использовать базу данных (очередь) на основе памяти, чтобы сохранить данные из вашего сценария, а затем получить к ним доступ из представления Django. Я рекомендую Redis для этого.


Пример сценария:

# start_server.py

import subprocess
import threading
import time


def ping():
    while True:
        print("Pinging ...") # do actual API pinging stuff here
        time.sleep(10)

t = threading.Thread(target=ping)
t.start() # this will run the `ping` function in a separate thread

# now start the django server
subprocess.call(['python', 'manage.py', 'runserver'])

Теперь все, что вам нужно сделать, это запустить python start_server.py, и он автоматически запустит сервер Django, а также функцию ping API.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...