RkBlog

Hardware, programming and astronomy tutorials and reviews.

Comet w Django

Tworzymy czat bez Javy i Flasha z pomocą orbited i django.

  • Comet i Orbited - Tworzenie aplikacje www czasu rzeczywistego z wykorzystaniem serwera Comet - Orbited.

  • Wykorzystanie cometa w aplikacjach www polega na "połączeniu" standardowego serwera HTTP odpowiedzialnego za działanie aplikacji z serwerem cometa. Porozumiewanie się aplikacji www z cometem zazwyczaj odbywa się poprzez żądania wysyłane przez ajaxa. Najprostsze połączenie orbited ze zwykłym serwerem HTTP polega na wykorzystaniu funkcji proxy w orbited. Wystarczy w katalogu, z którego go uruchamiamy stworzyć plik orbited.cfg o zawartości:
    [global]
    proxy.enabled = 1
    proxy.keepalive = 0
    
    [proxy]
    /chat -> ORBITED
    / -> http://127.0.0.1:8080
    
    Gdzie wszystkie żądania do "/chat" będą obsługiwane przez demon orbited, natomiast reszta przez serwer działający na porcie 8080 (np. serwer deweloperski Django). Strona dostępna jest na porcie 8000 - porcie używanym przez orbited.

    Tworzymy projekt django wyświetlający jeden szablon (bez bazy danych). Tworzymy szablon chat.html:
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Chat</title>
        <script src="/_/orbited.js"></script>
        <script type="text/javascript" src="/site_media/ajaxroutine.js"></script>
        <link rel="stylesheet" href="/site_media/chat.css">
        <script src="/site_media/chat.js" charset="utf-8"></script>
      </head>
      <body>
        <input type="text" id="nickname">
        <input type="button" value="nickname" name="nickname" onClick="connect();">
        <div id="box"></div>
        <input type="text" id="chat">
        <input type="submit" value="chat" onClick="send_msg();">
        <iframe id="events"></iframe>
      </body>
    </html>
    
    Powyższy szablon wyświetli "formularz" czata - pole na wiadomość i nick oraz okno treści. Ramka "events" posłuży do przesyłania zdarzeń. W katalogu na pliki statyczne dodajemy chat.css:
    body {
      margin-left:2em;
    }
    
    #box {
      border: 1px solid black;
      width: 80%;
      margin: .5em auto .5em 0;
      height: 10em;
      overflow: scroll;
    }
    
    .event {
      border: 1px dashed blue;
      margin: .5em auto;
      padding: .2em;
      width: 90%;
    }
    
    #events {
      display: none;
    }
    
    Oraz chat.js:
    function processGetPost()
    	{
    	var myajax=ajaxpack.ajaxobj
    	var myfiletype=ajaxpack.filetype
    	if (myajax.readyState == 4)
    		{ //if request of file completed
    		if (myajax.status==200 || window.location.href.indexOf("http")==-1)
    			{ //if request was successful or running script locally
    			if (myfiletype=="txt")
    			alert(myajax.responseText)
    			else
    			alert(myajax.responseXML)
    			}
    		}
    	}
    
    
    function connect()
    {
      var nick = document.getElementById('nickname').value;
      Orbited.connect(chat_event, nick, "/chat", "0");
      ajaxpack.getAjaxRequest("/join/" + nick + "/", "", processGetPost, "txt");
    }
    
    
    chat_event = function(data) {
      var chat_box = document.getElementById('box');
      var div = window.parent.document.createElement('div');
      div.className = "event";
      div.innerHTML = data;
      chat_box.appendChild(div);
      chat_box.scrollTop = chat_box.scrollHeight;
    }
    
    function send_msg() {
      var msg = document.getElementById('chat').value;
      var nick = document.getElementById('nickname').value;
      ajaxpack.getAjaxRequest("/send/" + nick + "/" + msg + "/", "", processGetPost, "txt");
    }
    
    Plik ajaxroutines.js pochodzi ze strony dynamicdrive.com, wystarczy go pobrać. Za jego pomocą w łatwy sposób obsłużymy żądania GET wysyłane do widoków aplikacji wysyłającej wiadomość (funkcja send_msg) oraz dodającej nowego użytkownika czatu (funkcja connect) stosując poniższe mapowanie odnośników w urls.py:
    urlpatterns = patterns('',
    (r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': 'ścieżka/do/plików_staycznych'}),
    (r'^join/(?P<nick>[\w\-_]+)/', 'chat.views.add_nick'),
    (r'^send/(?P<nick>[\w\-_]+)/(?P<msg>.*)/', 'chat.views.send_msg'),
    (r'^/?$', 'chat.views.chat_page'),
    )
    
    Kod widoków:
    from pyorbited.simple import Client
    
    from django.shortcuts import render_to_response
    from django.conf import settings
    from django.http import HttpResponse
    
    users = []
    orbit = Client()
    
    def chat_page(request, users=users, orbit=orbit):
    	"""
    	Główny widok wyświetlający szablon
    	"""
    	return render_to_response('chat.html', {})
    
    def add_nick(request, nick, users=users, orbit=orbit):
    	"""
    	Dodajemy nowego użytkownika do listy użytkowników-klientów orbited
    	"""
    	users.append((nick, '0'))
    	orbit.event(user_k(), '%s joined' % nick)
    	return HttpResponse("ok")
    
    def send_msg(request, nick, msg, users=users, orbit=orbit):
    	"""
    	Wysłanie wiadomości
    	"""
    	orbit.event(user_k(), '%s %s' % (nick, msg))
    	return HttpResponse("ok")
    
    def user_k(users=users):
    	"""
    	Stworzenie listy użytkowników-klientów obsługiwanych przez orbited
    	"""
    	lista = ["%s, %s, /chat" % (user[0], str(user[1]))
    		for user in users]
    	return lista
    
    Teraz uruchamiamy serwer django i orbited. Wystarczy otworzyć dwa okna przeglądarki ze stroną http://localhost:8000/. Zobaczymy "formularz" czatu. Na początek trzeba podać nick i "dołączyć" do czatu klikając w przycisk obok. Możemy już wysyłać wiadomości. Jeżeli w drugim oknie podamy inni nick i dołączymy do czatu to odpowiednia informacja pojawi się w pierwszym oknie. Teraz czat będzie w czasie rzeczywistym przekazywał wiadomości między tymi dwoma oknami - klientami serwera orbited.
    comet1
    Dodatkowe informacje i przykłady dla CherryPy czy Pylons znajdziemy na stronie projektu.
    RkBlog

    Django, 14 July 2008,

    Comment article