-
Допустим есть некий view, в котором выполняются некие действия:
нужные для отображения действия не нужные для отображения действия return
Хотелось бы делать подобным образом:
нужные для отображения действия return не нужные для отображения действия
Т.е отложенное выполнение необязательных для отображения, но нужных в данном контексте действий. Как вы решаете подобную задачу?
Для большей понятности можно привести пример, когда в view мы делаем выборку данных для показа + нам необходимо увеличить счетчик показа на 1. Счетчик в данном случае не нужен для отображения и для завершения view нам надо сделать лишнюю запись в БД. А было бы хорошо сначала отобразить данные, а уже потом сделать инкримент счетчика. Идея в общем-то такая. -
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. -
Есть два ответа на этот вопрос. Но перед этим я хочу подчеркнуть, что обычное веб-приложение на сервере вообще не живет за пределами обработки запросов пользователя (в отличие например от GUI-приложения). Как только пользователю сформирован и отдан ответ, работа веб-приложения в данном конкретном воплощении заканчивается. Поэтому деление вьюхи на части "нужную" и "ненужную" просто неверно в рамках веб-архитектуры. Если приложению нужно в принципе что-то делать, то оно это делает в ответ на запрос пользователя. То, что какие-то действия, возможно, не влияют на вид страницы, не повод их не делать.
Однако в принципе, так сделать можно. Для этого на сервере нужно иметь отдельный от веб-приложения процесс (называющийся часто "offline process", "off-site process", "standalone process"), которому веб-приложение будет во время обработки запроса что-то сигналить, и процесс будет это выполнять независимо от того, что веб-приложение обработало запрос и завершилось.
Второй ответ состоит в том, что в вашем случае так делать скорее всего не надо. Off-site процессы обычно делают для длинных тяжелых операций, которые пользователю незачем ждать. Если же речь идет о том, что надо увеличить счетчик, нет никаких причин делать это так сложно.
-
Dyadya Zed, причем тут сигналы? Они в любом случае выполняются синхронно, точно так же как любой прямой вызов функции. Никаким странным образом этот код не будет выполняться после того, как response ушел к клиенту.
-
Да, спосибо за ваши мнения.
Счетчик был просто ради примера. -
Что тогда означают вот эти строки в документации?
#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. -
В этих строках документации ничего не говорится про отложенное выполнение пользовательского callback'а. Да, формально "после return" из вьюхи с реквестом еще много чего происходит: он проходит через все response middleware, после этого вызываются все хэндлеры request_finished. Но суть в том, что это все не происходит отложенно, в чем и была суть вопроса. Все это происходит до того, как ответ возвращается веб-серверу, поэтому с точки зрения нужности/не нужности нет никакой разницы, вызвать какую-то функцию в конце своей view, прописать ее в middleware или повесить на сигнал request_finished. Разница только архитектурная.
-
Иван, спасибо за развернутый ответ. Я, в принципе, все так и представлял. Сам вопрос и пример со счетчиком немного не корректен, но видимо, автор вопроса нашел зерно истины :)
-
веб-приложение на сервере вообще не живет за пределами обработки запросов
Обработка запроса и отдача контента вещи разные. Насколько понял, тс спрашивал о втором. В общем случае его вопрос звучит как "можно ли отдавать контент постепенно".
Не разбирался, как сделать это в Джанге. Но Джанга 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)
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.


