Wygodny storage z użyciem memcache w Django
Czasami zachodzi konieczność napisania na szybko aplikacji w Django która standardowo coś tam trzyma w bazie danych, coś przetwarza i wyświetla. Jeśli aplikacja ma być prosta, a w bazie mają być trzymane proste struktury danych, to czy napewno musimy tyle czasu poświęcać na dopracowanie modeli? Jasne, że nie.
Poniższy kod oferuje nam możliwość trzymania dowolnych danych w postaci klucz-wartość w bazie danych. Dodatkowo — owe dane mogą mieć dowolną postać — może być to tekst, tablica asocjacyjna czy wartość typu Boolean.
Ponadto — biblioteczka ta opiera się o opisaną w poprzednim wpisie obsługę memcache'u w Django — co sprawia, że do póki nie zmienimy wartości danych, a ich obecność w cache'u nie zdąży wygasnąć — nie będziemy w ogóle obciążać naszej bazy danych. Osobiście wykorzystuję ten kod do trzymania ustawień aplikacji. Niektóre ustawienia są typu boolean, inne to stringi, jeszcze inne — tabele. Rozwiązanie sprawdza się świetnie.
Właściwy kod
Modele — models.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2009 nme.pl
# Dual licensed under MIT and GPL.
from django.db import models
class Vars (models.Model):
key = models.CharField(max_length=50)
value = models.TextField()
Proste prawda? Nie zapomnijcie wydać komendy django-admin syncdb która utworzy odpowiednią tabelę w bazie. Teraz czas na właściwą bibliotekę — vars.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2009 nme.pl
# Dual licensed under MIT and GPL.
""" Simple variables (key-value) handling with memcache """
import pickle,base64
import memcache,models
from settings import conf
class __Vars:
def get (self,key,default=None):
""" get Vars variable value """
if memcache.enabled:
value = memcache.get('va-%s' % key)
if value != None:
return pickle.loads(base64.b64decode(str(value)))
settings = models.Vars.objects.filter(key=key)
if settings:
value = settings[0].value
if value:
return pickle.loads(base64.b64decode(str(value)))
else:
return default
else:
return default
def __getitem__ (self,msg):
return self.get(key)
def set (self,key,value):
""" set Vars variable value """
value = base64.b64encode(pickle.dumps(value))
if memcache.enabled:
memcache.set('va-%s' % key,value)
settings = models.Vars.objects.filter(key=key)
if settings:
setting = settings[0]
setting.value = value
setting.save()
else:
models.Vars(key=key,value=value).save()
def has_key (self,key):
""" return True or False if Vars variable exists """
settings = models.Vars.objects.filter(key=key)
if settings:
return True
else:
return False
def delete (self,key):
""" deletes given key from Vars and memcache """
if memcache.enabled:
memcache.delete('va-%s' % key)
settings = models.Vars.objects.filter(key=key)
for i in settings:
i.delete()
variables = __Vars()
Przykładowe użycie
Zastosowanie biblioteki z poziomu django-admin shell:
In [1]: from vars import variables
In [2]: if not variables.has_key('test'):
...: variables.set('test','tekst')
...:
...:
In [3]: print variables.get('test')
tekst
In [4]: variables.set('test',{'asd':1,'data':['struct','ure']})
In [5]: variables.get('test')['data'][1]
Out[5]: 'ure'
In [6]: variables.delete('test')
In [7]: variables.get('test')
In [8]: variables.has_key('test')
Out[8]: False
Jak to działa?
Składowanie dowolnego typu danych w rekordzie bazy zrealizowane jest w oparciu o dwie standardowe biblioteki pythonowe — pickle i base64. Pierwsza z nich oferuje zakodowanie dowolnej struktury danych do stringa, druga natomiast — zastosowanie notacji base64 — przez co zabezpieczamy się przed ewentualnymi problemami z obsługą znaków z którymi nasz bazodanowy backend mógłby mieć ewentualnie problemy. Innymi słowy — rozwiązanie przedstawione powyżej gwarantuje nam pełną przenośność danych.
Zachęcam gorąco do korzystania 





