Django-Websocket-laajennos
Project description
django-pistoke
Django-laajennos, joka mahdollistaa Websocket-pyyntöjen käsittelemisen Django-näkymien kautta tasavertaisesti HTTP-pyyntöjen rinnalla.
Sisältää seuraavat työkalut:
-
Websocket-käsittelijä testi- ja tuotantokäyttöön
-
HTTP- ja Websocket-ohjaimet (middleware)
Käyttöönotto
Järjestelmävaatimukset
- Python 3.6 tai uudempi
- Django 3.1 tai uudempi
- ASGI-palvelinohjelmisto (tuotannossa): Daphne, Uvicorn, Hypercorn tms.
Asennus
pip install django-pistoke
Django-projektiasetukset
Lisää Django-projektiasetuksiin:
pistoke.Pistoke
asennettuihin sovelluksiin (ennen mahdollistastaticfiles
-sovellusta) japistoke.ohjain.WebsocketOhjain
asennettuihin ohjaimiin:
# projekti/asetukset.py
...
INSTALLED_APPS = [
...
'pistoke.Pistoke',
...
'django.contrib.staticfiles', # tarvittaessa
...
]
MIDDLEWARE = [
...
'pistoke.ohjain.WebsocketOhjain',
]
Tämä järjestys vaaditaan, jotta käsillä olevan paketin toteuttama runserver
-komento ohittaa staticfiles
-toteutuksen.
Jakeluun sisältyvä django-protoni
-yhteensopiva asetuslaajennos (pistoke/asetukset.py) tekee nämä lisäykset automaattisesti.
ASGI-määritys
Luo tai täydennä Django-projektin ASGI-määritystiedosto. Alla kuvattu esimerkkimääritys:
- alustaa Django-oletuskäsittelijän HTTP-pyynnöille,
- alustaa Pistoke-käsittelijän Websocket-pyynnöille ja
- ajaa kunkin saapuvan ASGI-pyynnön oikean käsittelijän läpi, jolloin pyyntö ohjautuu tavanomaisen Django-reititystaulun (
ROOT_URLCONF
) mukaiselle näkymälle riippumatta sen tyypistä.
# projekti/asgi.py
import os
from django.core.asgi import get_asgi_application
from pistoke.kasittelija import WebsocketKasittelija
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'projekti.asetukset')
kasittelija = {
'http': get_asgi_application(),
'websocket': WebsocketKasittelija(),
}
async def application(scope, receive, send):
return await kasittelija.get(scope['type'])(scope, receive, send)
Ohjaimet
Ohjaimet HTTP-pyynnöllä
Käsillä oleva paketti sisältää tavanomaisen Django/HTTP-ohjaimen pistoke.ohjain.WebsocketOhjain
, joka asettaa saapuvalle HTTP-pyynnölle määritteen websocket
.
- tämä sisältää URI-osoitteen, esim.
ws://palvelin.org
, Websocket-pyyntöjen ohjaamiseksi samalle palvelimelle (http://palvelin.org
) kuin kyseinen HTTP-pyyntö; - mikäli HTTP-yhteys on salattu (esim.
https://palvelin.org
), käytetään salattua Websocket-protokollaa:wss://palvelin.org
.
Ohjaimet Websocket-pyynnöllä
Tavanomaiset Django-ohjaimet ajetaan Websocket-pyynnölle samalla tavoin kuin HTTP-pyynnölle, pl. HTTP-paluusanoman käsittely.
CSRF-ohjainta muokataan siten, että saapuvan Websocket-pyynnön CSRF-tunnistetta ei yritetä tarkistaa ohjaimessa (sitä ei ole saatavilla ilman POST-dataa). Sen sijaan pyynnölle lisätään metodi tarkista_csrf
Websocket-yhteyden kautta vastaanotetun CSRF-datan tarkistamiseksi ajonaikaisesti.
Lisäksi Websocket-pyynnöille käytetään ohjainta, joka tarkistaa web-selaimen asettaman Origin
-otsakkeen arvon. Ohjain hyväksyy oletusarvoisesti vain ALLOWED_HOSTS
-asetuksen mukaiset pyyntölähteet; muista lähteistä tuleville pyynnöille palautuu hylkäävä paluusanoma (403).
Websocket-protokolla
Kullekin Websocket-pyyntöjä käsittelevälle näkymälle on määriteltävä protokolla, jonka mukaan yhteys luodaan ja katkaistaan ja viestinvälitys tapahtuu.
Näkymä voi joko
- itse toteuttaa ASGI-määrityksen mukaisen viestinvaihdon (
{"type": "websocket.connect"}
,{"type": "websocket.send", "text": "..."}
jne.), - käyttää käsillä olevan paketin tarjoamaa protokollatoteutusta:
pistoke.protokolla.WebsocketProtokolla
ja sen alaluokat; tai - käyttää oletusarvoista protokolla joka otetaan automaattisesti käyttöön.
Protokollaa käytetään sellaisenaan koristeena Websocket-näkymäfunktiolle tai Django-method_decoratorin
avulla koristeena näkymäluokan websocket
-metodille.
Huomaa, että samaan näkymään liittyvien koristeiden keskinäisellä määritysjärjestyksellä on merkitystä. Kun Websocket-näkymässä käytetään protokollan P
lisäksi esimerkiksi Django-pääsynhallintaan liittyvää koristetta D
:
- Mikäli protokolla
P
on sisempänä (alempana) kuinD
, palautuu käyttäjälle tavanomainen HTTP-virhesanoma 401 tai 403, kun oikeudet eivät riitä. - Mikäli protokolla
P
on ulompana (ylempänä) kuinD
, avautuu Websocket-yhteys normaalisti myös silloin, kun oikeudet eivät riitä. Yhteys kuitenkin päättyy tällöin heti poikkeukseen.
Huomaa, että käsillä olevan paketin toteuttama automaattinen protokollamääritys muodostaa aina uloimman kerroksen näkymän ympärillä.
Yleiskäyttöisen kantaluokan (WebsocketProtokolla
) lisäksi käytettävissä ovat seuraavat, rajatumpiin tilanteisiin soveltuvat protokollat:
WebsocketAliProtokolla("protokolla-a", "protokolla-b")
: Websocket-aliprotokollamääritysWebsocketJSONProtokolla
: JSON-muotoinen viestinvaihto.
Yhteensopivuus: django-pistoke v0.x vs. v1.x
Yhteensopivuuden varmistamiseksi taaksepäin käytetään versioon 1.1 asti seuraavaa automatiikkaa:
- mikäli Websocket-näkymälle on asetettu jokin edellä mainittu protokolla, sitä käytetään sellaisenaan
- muussa tapaksessa näkymä koristellaan automaattisesti
WebsocketProtokolla
-tyyppiseksi.
Versioon 1.2 asti on lisäksi käytettävissä seuraava ohitus edellämainittuun automatiikkaan:
- mikäli näkymäluokka toteuttaa itse ASGI-viestinvaihdon, tämä voidaan määrittää
TyhjaWebsocketProtokolla
-koristetta käyttäen.
Websocket-näkymä
Websocket-käsittelijä ohjaa saapuvat pyynnöt Django-näkymille tavanomaisen urlpatterns
-reititystaulun mukaisesti. Websocket-pyynnön metodiksi (request.method
) asetetaan Websocket
. Näkymän toteutus voi olla funktio- tai luokkapohjainen:
django.views.generic.View.dispatch
ohjaa WS-pyynnön käsiteltäväksi näkymäluokanwebsocket
-metodiin;- funktiopohjainen näkymä voi vastata pyynnön metodin perusteella eri tavoin HTTP- ja Websocket-pyyntöihin.
Kummassakin tapauksessa WS-pyynnön käsittelystä vastaavan metodin tai funktion tulee olla tyyppiä async def
.
Huomaa, että luokkapohjaisen näkymän tapauksessa Websocket
-metodi pitää erikseen sallia näkymäluokalle (HTTP-metodien kuten GET
ja POST
ohella), jotta tämän tyyppiset pyynnöt sallitaan. Saateluokka pistoke.nakyma:WebsocketNakyma
tekee tämän automaattisesti.
Seuraava listaus on esimerkki yhdysrakenteisesta, luokkapohjaisesta näkymätoteutuksesta, joka
- palauttaa GET-pyynnöllä Django-sivuaihion ja
- vastaa Websocket-pyyntöön jatkuvana viestivaihtona:
# sovellus/nakyma.py
from django.urls import path
from django.utils.decorators import method_decorator
from django.views import generic
from pistoke.nakyma import WebsocketNakyma
from pistoke.protokolla import WebsocketProtokolla
@method_decorator(WebsocketProtokolla(), name='websocket')
class Nakyma(WebsocketNakyma, generic.TemplateView):
template_name = 'sovellus/nakyma.html'
async def websocket(self, request, *args, **kwargs):
while True:
syote = await request.receive()
if isinstance(syote, str):
await request.send(
f'Kirjoitit "{syote}".'
)
elif isinstance(syote, bytes):
await request.send(
f'Kirjoitit "{syote.decode("latin-1")}".'.encode('latin-1')
)
# white True
# async def websocket
# class Nakyma
urlpatterns = [path('nakyma/', Nakyma.as_view())]
Esimerkki tähän näkymään liittyvästä HTML-aihiosta:
<!-- sovellus/templates/sovellus/nakyma.html -->
<input
id="syote"
type="text"
placeholder="Syötä viesti"
/>
<button
onclick="websocket.send(document.getElementById('syote').value);"
>Lähetä</button>
<script>
websocket = new WebSocket(
"{{ request.websocket }}{{ request.path }}"
);
websocket.onmessage = function (e) { alert(e.data); };
</script>
ASGI-kehityspalvelin
Paketti sisältää runserver
-ylläpitokomentototeutuksen (Django-kehityspalvelin), joka periytetään joko:
- Djangon tavanomaisesta
runserver
-komennosta tai django.contrib.staticfiles
-sovelluksen periyttämästä komennosta, mikäli tämä on asennettu.
Käsillä olevan paketin toteuttama runserver
lisää seuraavat vivut edellä mainittuihin toteutuksiin nähden:
- vipu
--wsgi
käynnistää tavanomaisen (sisäänrakennetun) WSGI-palvelimen; - vipu
--asgi
käynnistää ASGI-palvelimen (uvicorn
-pakettia käyttäen); - oletus näistä on ASGI, jos ja vain jos
uvicorn
on asennettu.
Huomaa, että --asgi
-vipu edellyttää Uvicorn-paketin asentamisen ja aiheuttaa poikkeuksen, mikäli tätä ei löydy.
Vakiona runserver
-komennon hyväksymä --verbose
-vipu hyväksyy, silloin kuin käytössä on --asgi
-tila, tavanomaisten numeroarvojensa (0–3) lisäksi myös uvicorn --log-level
-vivun hyväksymät tekstimuotoiset määreet:
critical
: vastaa Django-tasoa 0error
warning
info
: vastaa Django-tasoa 1debug
: vastaa Django-tasoa 2trace
: vastaa Django-tasoa 3
Palvelinasennus
Palvelinasennukseen sopii hyvin vaikkapa yhdistelmä Nginx + Circus + Uvicorn; ks. https://www.uvicorn.org/deployment/#running-behind-nginx.
Käyttöesimerkkejä
- Reaaliaikainen keskusteluyhteys kahden käyttäjän välillä: django-juttulaatikko
- Datan reaaliaikainen, kaksisuuntainen synkronointi Django-palvelimen ja selaimen välillä Websocket-yhteyden välityksellä: django-synkroni
- Xterm-pääteyhteys Django-sovelluksena: django-xterm
- Django-ilmoitusten (
messages
) reaaliaikainen toimitus selaimelle Celery-pinon ja Websocket-yhteyden avulla: django-celery-ilmoitus - jQuery-Datatables-liitännäinen Websocket-pohjaiseen tiedonsiirtoon erillisten Ajax-pyyntöjen asemesta: datatables-websocket
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file django_pistoke-0.9.6.tar.gz
.
File metadata
- Download URL: django_pistoke-0.9.6.tar.gz
- Upload date:
- Size: 25.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d235f0e699812d0aef8f2bdd7c1342ed8ad68f90d0956ad6ca2854f580f858ed |
|
MD5 | 36a325956c537490050b2a94fae35620 |
|
BLAKE2b-256 | 8058ef8b3532b32f5ee7ca6f0d41de1a6efdc22e8a290b48488b7ccf633d92e6 |
File details
Details for the file django_pistoke-0.9.6-py3-none-any.whl
.
File metadata
- Download URL: django_pistoke-0.9.6-py3-none-any.whl
- Upload date:
- Size: 29.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | b1b545e8f5c585a5ece2c8185665df578f3dc5723d12d2a359a00c3c3934f117 |
|
MD5 | d9386ce9c6c57af59428b16029d37cae |
|
BLAKE2b-256 | 00b8e43c9c664247e03776d6eae1fcf62a4d1db6197a6cef006e41bc81391f07 |