23.05.2009 16:53

  1. Анонимно

    0 ↑
    0 ↓
    Допустим есть некий view, в котором выполняются некие действия:

    
     нужные для отображения действия
     не нужные для отображения действия
     return
    


    Хотелось бы делать подобным образом:

    
     нужные для отображения действия
     return
     не нужные для отображения действия
    


    Т.е отложенное выполнение необязательных для отображения, но нужных в данном контексте действий. Как вы решаете подобную задачу?

    Для большей понятности можно привести пример, когда в view мы делаем выборку данных для показа + нам необходимо увеличить счетчик показа на 1. Счетчик в данном случае не нужен для отображения и для завершения view нам надо сделать лишнюю запись в БД. А было бы хорошо сначала отобразить данные, а уже потом сделать инкримент счетчика. Идея в общем-то такая.
  2. http://docs.djangoproject.com/en/dev/topics/signals/#topics-signals

    Connecting receiver functions¶

    Next, we'll need to connect our receiver to the signal:
    
    from django.core.signals import request_finished
    request_finished.connect(my_callback)
    


    Now, our my_callback function will be called each time a request finishes.
  3. Есть два ответа на этот вопрос. Но перед этим я хочу подчеркнуть, что обычное веб-приложение на сервере вообще не живет за пределами обработки запросов пользователя (в отличие например от GUI-приложения). Как только пользователю сформирован и отдан ответ, работа веб-приложения в данном конкретном воплощении заканчивается. Поэтому деление вьюхи на части "нужную" и "ненужную" просто неверно в рамках веб-архитектуры. Если приложению нужно в принципе что-то делать, то оно это делает в ответ на запрос пользователя. То, что какие-то действия, возможно, не влияют на вид страницы, не повод их не делать.

    Однако в принципе, так сделать можно. Для этого на сервере нужно иметь отдельный от веб-приложения процесс (называющийся часто "offline process", "off-site process", "standalone process"), которому веб-приложение будет во время обработки запроса что-то сигналить, и процесс будет это выполнять независимо от того, что веб-приложение обработало запрос и завершилось.

    Второй ответ состоит в том, что в вашем случае так делать скорее всего не надо. Off-site процессы обычно делают для длинных тяжелых операций, которые пользователю незачем ждать. Если же речь идет о том, что надо увеличить счетчик, нет никаких причин делать это так сложно.

  4. Dyadya Zed, причем тут сигналы? Они в любом случае выполняются синхронно, точно так же как любой прямой вызов функции. Никаким странным образом этот код не будет выполняться после того, как response ушел к клиенту.

  5. Анонимно

    0 ↑
    0 ↓
    Да, спосибо за ваши мнения.

    Счетчик был просто ради примера.
  6. Что тогда означают вот эти строки в документации?

    #django.core.signals.request_started & django.core.signals.request_finished

    Sent when Django starts or finishes an HTTP request.

    и далее

    Now, our my_callback function will be called each time a request finishes.
  7. В этих строках документации ничего не говорится про отложенное выполнение пользовательского callback'а. Да, формально "после return" из вьюхи с реквестом еще много чего происходит: он проходит через все response middleware, после этого вызываются все хэндлеры request_finished. Но суть в том, что это все не происходит отложенно, в чем и была суть вопроса. Все это происходит до того, как ответ возвращается веб-серверу, поэтому с точки зрения нужности/не нужности нет никакой разницы, вызвать какую-то функцию в конце своей view, прописать ее в middleware или повесить на сигнал request_finished. Разница только архитектурная.

  8. Иван, спасибо за развернутый ответ. Я, в принципе, все так и представлял. Сам вопрос и пример со счетчиком немного не корректен, но видимо, автор вопроса нашел зерно истины :)
  9. Imbolc

    0 ↑
    0 ↓

    веб-приложение на сервере вообще не живет за пределами обработки запросов

    Обработка запроса и отдача контента вещи разные. Насколько понял, тс спрашивал о втором. В общем случае его вопрос звучит как "можно ли отдавать контент постепенно".

    Не разбирался, как сделать это в Джанге. Но Джанга wsgi-фреймворк, а последний позволяет отдавать контент постепенно:

    def application(environ, start_response):
        start_response('200 OK', [('Content-type', 'text/plain')])
        for i in xrange(100):
            yield '%i\n' % i
            time.sleep(1)
    

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.