Pogledajte određenu poruku
Staro 24. 05. 2012.   #10
djipko
član
Certified
 
Avatar djipko
 
Datum učlanjenja: 03.10.2006
Poruke: 96
Hvala: 27
44 "Hvala" u 26 poruka
djipko is on a distinguished road
Default

Naravno da postoje razni gotovi mapperi ali svaka dodatna biblioteka u projektu zna da ima i svoju cenu. ODM-i nisu teski i mogu biti zabavni za pisanje, posebno ako ti za tvoje potrebe ne treba sva masinerija koju nude OSS resenja.

Posto sam obecao primer evo ga za python. Primer je vrlo jednostavan mada ovo sve moze mnogo vise da se zakomplikuje.

Dakle osnovna klasa i globalno mesto gde se registruju modeli i verzije bi bili u modulu koji bi izgledao otprilike ovako:

Kôd:
from pymongo import Connection

version_reg = {} #"Globalni" dict koji cuve verzije

def register_version_model(cls, version):
    """Registruj klasu koja je model za odredjenu verziju scheme"""
    version_reg[version] = cls

def get_version_by_model(cls):
    """Vrati za koju verziju scheme je registrovana klasa"""
    for v, c in version_reg.iteritems():
        if c is cls: return v
    return None
    
class MongoBaseModel(object):
    """Klasa koju svi mongo modeli nasledjuju, i redefinisu potrebne metode"""

    _db = 'test_db'
    _collection = 'test_col'

    def _to_dict(self):
        """
        Ova metoda mora da se redefinise - ona ustvari 
        sadrzi logiku predstave modela u bazi.
        """
        raise NotImplementedError

    def save(self):
        #Napravi od sebe dict
        d = self._to_dict() 
        #vidi gde si registrovan, i zapisi to u bazu
        d['version'] = get_version_by_model(self.__class__) 
        Connection()[self._db][self._collection].insert(d)

    @classmethod
    def read(cls, spec):
        """
        Metoda procita dokument ako postoji, i na osnovu verzije konstruise
        objekat i vrati ga
        """
        doc = Connection()[self._db][self._collection].find_one(spec)
        if doc:
            model_cls = version_reg.get(doc['version'], None)
            if not model_cls:
                raise ValueError("No model registered for this version")
            return model_cls(doc)
        return None
I onda zatim pravis svoj model (evo ga jako jednostavan primer):

Kôd:
class Calculation(MongoBaseModel)
    """Zamisljena klasa kalkulacije ciji se rez cuva u bazu"""
    def __init__(self, doc):
        self.date = doc['date']
        self.result = doc['result']
    
    def _to_dict(self):
        """Obrnuto od konstruktora - u ovom primeru nezanimljivo"""
        return dict(
            date = self.date
            result = self.result
        )
Koji i registrujes sa:

Kôd:
register_version_model(Calculation, 1)
E sada kada je model potrebno malo izmeniti:

Kôd:
class NewCalculation(MongoBaseModel)
    """Nova klasa kalkulacije koja sada cuva i koliko je kalc trajala"""
    def __init__(self, doc):
        self.date = doc['date']
        self.result = doc['result']
        self.duration = doc['duration']
    
    def _to_dict(self):
        """Obrnuto od konstruktora - u ovom primeru nezanimljivo"""
        return dict(
            date = self.date
            result = self.result
            duration = self.duration
        )

register_version_model(NewCalculation, 2)
Ono sto se ne vidi iz primera je da ako ove dve klase nasledjuju od trece klase koja definise neki interfejs za rad (i pegla nesuglasice) - potpuno si se resio glavobolje tipa - "sta sam to procitao??". Nekad je OO i dobar

Kao sto sam rekao moze ovo mnogo vise da se zakomplikuje i nabudzi (metaprogramiranjem i slicnim cakama), naravno fale provere gresaka itd. ali funkcionalni, mali i lagani ODM ne trazi mnogo vise od ovih 30ak linija u Pythonu, bez da se patis sa nekim bloat-om sa github-a.

Ako nekome neka python-specific caka nije jasna (mada ih bas i nema u gornjem kodu) rado cu pojasniti.

Poslednja izmena od djipko : 24. 05. 2012. u 21:17.
djipko je offline   Odgovorite uz citat
"Hvala" djipko za poruku: