Edited at

DjangoでServer-Sent Eventsを行う方法

More than 1 year has passed since last update.

DjangoでWebSocketやるには時間が足りないけどサーバーサイドpushをしたかったので、ゴリ押しでSSRを使って対処することにしました

修正点があれば指摘していただけると幸いです


注意

ローカルサーバーで実験した所、接続を中断させた時に[ConnectionAbortedError: [WinError 10053] 確立された接続がホスト コンピューターのソウトウェアによって中止されました。]というエラーメッセージが出ます

恐らく無害だと思いますが、気持ち悪いので扱う時は気をつけて下さい


そもそもServer-Sent Eventsって何よ

ざっくり言うとすごいCometです。つまりゴリ押しサーバーサイドpushみたいなものです

WebSocketの方が優秀かもしれませんが、実装コストが低いのがメリットです

詳しく知りたい方は調べて下さい。


コード内容概要

SSEをするだけ。他のIDなどの機能は一切省く


コード


Python側

ストリーミング配信を行う


views.py

from django.views.decorators.http import condition

from django.http import StreamingHttpResponse
from django.views.generic import UpdateView, DetailView, FormView, TemplateView, DeleteView
import time

@condition(etag_func=None)
def stream_response(request):
resp = StreamingHttpResponse(stream_response_generator(), content_type='text/event-stream')
return resp

def stream_response_generator():
while(True):
yield "data: %s\n" \
"retry:1000\n\n" % 0
time.sleep(1)

class DevSSETemplate(TemplateView):
template_name = "stream.html"



urls.py

    url(r'^stream/$', views.stream_response, name='stream_response'),

url(r'^stream/template/$', DevSSETemplate.as_view(), name='stream_response_template'),


JavaScript側

取得してリストに加えるだけ


stream.html

<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id ="log"></div>
</body>
<script>

window.onload = function() {
var evtSource = new EventSource("{% url 'accounts:stream_response' %}");
var eventList = document.getElementById("log");

evtSource.onmessage = function(e) {
console.log(e);
var newElement = document.createElement("li");

newElement.innerHTML = "message: " + e.data;
eventList.appendChild(newElement);
};
}

</script>
</html>



解説

@.condition(etag_func=None)

ETag(キャッシュ周り)を無効化する?

StreamingHttpResponse

このメソッドを使うとストリーミング配信が出来る。普段はPDFなどを送信する時に使うそうです

これを含め、Djangoには機能なものが多く、痒い所に手が届くのはありがたいです


感想

これで一応動きました

SSEは実装コストが低く、WebSocketのサポートが進んでないフレームワークでは有用であると思われるが、恐らくダサいから何故か流行らないのが不思議です