python / expert
Snippet
Django Session Management mit Custom Backend
Django's Session-Framework ist erweiterbar und erlaubt Custom Storage Backends jenseits der Standard-Datenbank-, Cache- oder Datei-basierten Optionen. Diese Implementierung zeigt einen Redis-basierten Session Store mit Sub-Millisekunden Lese/Schreib-Operationen, automatischer Ablaufzeit via TTL und atomaren Speicher-Operationen mit CreateError-Handling für must_create-Szenarien. Custom Backends sind unerlässlich für hochfrequentierte Anwendungen mit Horizontaler Skalierung.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import jsonfrom django.contrib.sessions.backends.base import SessionBase, CreateErrorfrom django.db import transactionclass RedisSessionStore(SessionBase):engine = 'django.contrib.sessions'prefix = 'session:'def __init__(self, session_key=None):super().__init__(session_key)self._redis = self._get_redis_client()def _get_redis_client(self):import django.conf as confcfg = conf.settings.SESSION_ENGINE_CONFIGimport redisreturn redis.Redis(host=cfg.get('HOST', 'localhost'),port=cfg.get('PORT', 6379),db=cfg.get('DB', 0),password=cfg.get('PASSWORD', None))@propertydef key(self):return self._get_or_create_session_key()def _get_redis_key(self, key=None):return f"{self.prefix}{key or self._get_or_create_session_key()}"def load(self):data = self._redis.get(self._get_redis_key())return json.loads(data) if data else {}def exists(self, session_key):return self._redis.exists(self._get_redis_key(session_key)) > 0@transaction.atomicdef save(self, must_create=False):key = self._get_or_create_session_key()if must_create and self.exists(key):raise CreateErrordata = json.dumps(self._session)self._redis.setex(self._get_redis_key(key), self.get_expiry_age(), data)def delete(self, session_key=None):self._redis.delete(self._get_redis_key(session_key or self._session_key))
django
Erklärung
1
class RedisSessionStore(SessionBase):
Custom Session Store erbt von Django's SessionBase abstrakter Klasse
2
def load(self):
Ruft Session-Daten aus Redis ab, gibt leeres Dict zurück wenn fehlend
3
def exists(self, session_key):
Prüft ob Session-Key in Redis existiert mittels EXISTS-Kommando
4
@transaction.atomic
Stellt sicher, dass Speicher-Operation atomar ist um Partial Writes zu verhindern
5
def save(self, must_create=False):
Persistiert Session zu Redis mit Ablaufzeit mittels SETEX-Kommando
6
self._redis.setex(..., self.get_expiry_age(), data)
SETEX setzt Wert mit Ablaufzeit in Sekunden (Redis eingebautes TTL)