12
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DjangoでServer-Sent Eventsを行う方法

Last updated at Posted at 2016-11-02

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のサポートが進んでないフレームワークでは有用であると思われるが、恐らくダサいから何故か流行らないのが不思議です

12
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?