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.Pistokeasennettuihin sovelluksiin (ennen mahdollistastaticfiles-sovellusta) japistoke.ohjain.WebsocketOhjainasennettuihin 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.WebsocketProtokollaja 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
Pon sisempänä (alempana) kuinD, palautuu käyttäjälle tavanomainen HTTP-virhesanoma 401 tai 403, kun oikeudet eivät riitä. - Mikäli protokolla
Pon 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.dispatchohjaa 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
--wsgikäynnistää tavanomaisen (sisäänrakennetun) WSGI-palvelimen; - vipu
--asgikäynnistää ASGI-palvelimen (uvicorn-pakettia käyttäen); - oletus näistä on ASGI, jos ja vain jos
uvicornon 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 0errorwarninginfo: 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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_pistoke-0.9.11.tar.gz.
File metadata
- Download URL: django_pistoke-0.9.11.tar.gz
- Upload date:
- Size: 26.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c79e9e08b8f061a600eb09a25993d73b72ba391c8f5618e5d62513b4955e7b8
|
|
| MD5 |
9d19a6a2e972d57a6881707209eb43be
|
|
| BLAKE2b-256 |
1f20cd9e6e2073be725e3677eddcc0b47589cba0e8bfc974aaf5b25dbd80f208
|
Provenance
The following attestation bundles were made for django_pistoke-0.9.11.tar.gz:
Publisher:
ci.yaml on an7oine/django-pistoke
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_pistoke-0.9.11.tar.gz -
Subject digest:
2c79e9e08b8f061a600eb09a25993d73b72ba391c8f5618e5d62513b4955e7b8 - Sigstore transparency entry: 601205709
- Sigstore integration time:
-
Permalink:
an7oine/django-pistoke@aad267f9aa13aa4ea8bf72f96b1b96ec018c1fc6 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/an7oine
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yaml@aad267f9aa13aa4ea8bf72f96b1b96ec018c1fc6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_pistoke-0.9.11-py3-none-any.whl.
File metadata
- Download URL: django_pistoke-0.9.11-py3-none-any.whl
- Upload date:
- Size: 30.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf3cdc1e7f6321f3cb50fbc410a3378b3637ec1b5eb0b4ceb27bc623f94dface
|
|
| MD5 |
e1b3176f775e787d3852a4ba8561eb8d
|
|
| BLAKE2b-256 |
6e2bf68dbef0307e8ee8cb5cd7727f34cdc7722c6e474bcf47abf672b793455a
|
Provenance
The following attestation bundles were made for django_pistoke-0.9.11-py3-none-any.whl:
Publisher:
ci.yaml on an7oine/django-pistoke
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_pistoke-0.9.11-py3-none-any.whl -
Subject digest:
bf3cdc1e7f6321f3cb50fbc410a3378b3637ec1b5eb0b4ceb27bc623f94dface - Sigstore transparency entry: 601205711
- Sigstore integration time:
-
Permalink:
an7oine/django-pistoke@aad267f9aa13aa4ea8bf72f96b1b96ec018c1fc6 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/an7oine
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yaml@aad267f9aa13aa4ea8bf72f96b1b96ec018c1fc6 -
Trigger Event:
push
-
Statement type: