--- On Fri, 11/20/09, Conor <[email protected]> wrote:

> 
> Also, there is a recipe that looks for a matching object in
> the session
> before querying the database:
> http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject
> 
> -Conor
> 

Thank you Conor for you useful pointer. I have used this recipe and changed a 
little bit to use beaker as a caching mechanism with a memcached backend. So 
here's how it looks like :

from elixir import Entity, EntityMeta,setup_all,create_all,metadata
from pylons import cache

class MetaTag(EntityMeta):
    cache = cache.get_cache("tags",type="memory")
    def __call__(cls,name):
        """
        If it's in the cache, return the cached version
        If not in the cache :
            If it's in the database, retrieve it, cache it and return it
            If it's not there, create it, cache it and return it
        """
        theTag = MetaTag.cache.get_value(key=name,createfunc=lambda:None)
        if not theTag :
            #not in the cache
            theTag = cls.query.filter_by(name=name).first()
            if not theTag:
                #not in the database either
                print "not in the database"
                theTag = type.__call__(cls,name)
                session.add(theTag)
            #Adding it to the cache, after creating it in the database if it 
wasn't there
            MetaTag.cache.set_value(key=name,value=theTag)            
        return theTag
    
class Tag(Entity):
    __metaclass__ = MetaTag
    using_options (tablename="Tags")
    name   = Field(Unicode(64))

    def __init__(self,name,*args,**kw):
        Entity.__init__(self,*args,**kw)
        self.name = name

    def __repr__(self):
        return "<Tag %s>" %  self.name

metadata.bind = "mysql://username:passw...@localhost:3306/db"
metadata.bind.echo = True

setup_all()
create_all()

And here's how it plays on the interpreter (ipython) :
Alger is already in the database, Constantine is not. I find the metaclass 
approach very API-friendly.

...

In [4]: Tag("Alger")
21:38:21,328 INFO  [sqlalchemy.engine.base.Engine.0x...2fec] BEGIN
/home/chaouche/PYTHONENV/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/engine/default.py:230:
 SAWarning: Unicode type received non-unicode bind param value 'Alger'
  param.append(processors[key](compiled_params[key]))
21:38:21,382 INFO  [sqlalchemy.engine.base.Engine.0x...2fec] SELECT `Tags`.id 
AS `Tags_id`, `Tags`.name AS `Tags_name` 
FROM `Tags` 
WHERE `Tags`.name = %s 
 LIMIT 0, 1
21:38:21,382 INFO  [sqlalchemy.engine.base.Engine.0x...2fec] ['Alger']
Out[4]: <Tag Alger>

In [5]: Tag("Alger")
Out[5]: <Tag Alger>

In [8]: Tag("Constantine")
/home/chaouche/PYTHONENV/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/engine/default.py:230:
 SAWarning: Unicode type received non-unicode bind param value 'Constantine'
  param.append(processors[key](compiled_params[key]))
21:39:17,487 INFO  [sqlalchemy.engine.base.Engine.0x...2fec] SELECT `Tags`.id 
AS `Tags_id`, `Tags`.name AS `Tags_name` 
FROM `Tags` 
WHERE `Tags`.name = %s 
 LIMIT 0, 1
21:39:17,487 INFO  [sqlalchemy.engine.base.Engine.0x...2fec] ['Constantine']
not in the database
Out[8]: <Tag Constantine>

In [9]: Tag("Constantine")
Out[9]: <Tag Constantine>

Any comments are very appreciated.

Y.Chaouche



      

--

You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=.


Reply via email to