Thursday, March 29, 2012

使用Traversal来配置Pyramid项目(四)复杂Traversal案例

四、一个复杂的案例

models.py
---------------------------
from sqlalchemy import (
    Column,
    Integer,
    Text,
    and_,
    )

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy.orm import (
    scoped_session,
    sessionmaker,
    )

from zope.sqlalchemy import ZopeTransactionExtension

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()

class MyCat(Base):
    __tablename__ = 'mycat'
    id = Column(Integer, primary_key=True)
    name = Column(Text, unique=True)
    pid = Column(Integer)
    desc = Column(Text)

    def __init__(self, name, pid, desc):
        self.name = name
        self.pid = pid
        self.desc = desc
        
    def __getitem__(self, key):
        session= DBSession()
        
        is_file = False
        try:
            key.index(".")
            is_file = True
        except: pass
        
        if is_file:
            item = session.query(MyFile).filter(and_(MyFile.name==key, MyFile.cat==self.id)).first()
        else:
            item = session.query(MyCat).filter(and_(MyCat.name==key, MyCat.pid==self.id)).first()

        if item is None:
            raise KeyError(key)

        item.__parent__ = self
        item.__name__ = key
        return item

    def get(self, key, default=None):
        try:
            item = self.__getitem__(key)
        except KeyError:
            item = default
        return item

    def listall(self):
        session= DBSession()
        cats = session.query(MyCat).filter(MyCat.pid==self.id).all()
        files = session.query(MyFile).filter(MyFile.cat==self.id).all()
        return cats + files

class MyFile(Base):
    __tablename__ = 'myfile'
    id = Column(Integer, primary_key=True)
    name = Column(Text, unique=True)
    cat = Column(Integer)
    save_path = Column(Text)
    desc = Column(Text)

    def __init__(self, name, cat, save_path, desc):
        self.name = name
        self.cat = cat
        self.save_path = save_path
        self.desc = desc


class MyRoot(object):
    __name__ = None
    __parent__ = None

    def __getitem__(self, key):
        session= DBSession()

        item = session.query(MyCat).filter(and_(MyCat.name==key, MyCat.pid==0)).first()
        if item is None:
            raise KeyError(key)

        item.__parent__ = self
        item.__name__ = key
        return item

    def get(self, key, default=None):
        try:
            item = self.__getitem__(key)
        except KeyError:
            item = default
        return item

    def __iter__(self):
        session= DBSession()
        query = session.query(MyCat).filter(MyCat.pid==0)
        return iter(query)

root = MyRoot()

def root_factory(request):
    return root



views.py
--------------------------
from .models import (
    DBSession,
    MyCat,
    MyFile,
    )

def view_root(context, request):
    print request.resource_url(context)
    return {'context':context, 'items':list(context), 'project':'MyTest'}

def view_cat(context, request):
    print request.resource_url(context)
    return {'context':context, 'items':context.listall(), 'project':'MyTest'}

def view_file(context, request):
    print request.resource_url(context)
    return {'item':context, 'project':'MyTest'}

def view_photo(context, request):
    return {'item':context, 'project':'MyTest'}


__init__.py
--------------------------
from pyramid.config import Configurator
from sqlalchemy import engine_from_config

from .models import (
    DBSession, 
    root_factory,
    )

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    config = Configurator(settings=settings, root_factory=root_factory)
    config.add_static_view('static', 'static', cache_max_age=3600)


    config.add_view('traverseonrdb.views.view_root', 
                    context='traverseonrdb.models.MyRoot', 
                    renderer="templates/root.pt")
    config.add_view('traverseonrdb.views.view_cat', 
                    context='traverseonrdb.models.MyCat', 
                    renderer="templates/cat.pt")

    config.add_view('traverseonrdb.views.view_photo',
                    name="photoview",
                    context='traverseonrdb.models.MyFile',
                    renderer="templates/photo.pt")    
    
    config.add_view('traverseonrdb.views.view_file',
                    context='traverseonrdb.models.MyFile',
                    renderer="templates/file.pt")

    return config.make_wsgi_app()


populate.py
--------------------------
# -*- coding: UTF-8 -*-

import os
import sys
import transaction

from sqlalchemy import engine_from_config

from pyramid.paster import (
    get_appsettings,
    setup_logging,
    )

from ..models import (
    DBSession,
    MyCat,
    MyFile,
    Base,
    )

def usage(argv):
    cmd = os.path.basename(argv[0])
    print('usage: %s <config_uri>\n'
          '(example: "%s development.ini")' % (cmd, cmd)) 
    sys.exit(1)

#直接在数据库中构建如下初始数据以供演示。
#MySite ---- MyPhoto ---- SportPhoto ---- ski.jpg
#         |            |
#         |            -- PrivatePhoto ---- love.jpg
#         |
#         -- MyNote ---- 20120327.txt
#         |
#         -- MyMP3 ---- paradise.mp3
#         |
#         -- MyVideo ---- hot.avi
def main(argv=sys.argv):
    if len(argv) != 2:
        usage(argv)
    config_uri = argv[1]
    setup_logging(config_uri)
    settings = get_appsettings(config_uri)
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    Base.metadata.create_all(engine)
    with transaction.manager:
        my_photo_cat = MyCat(name='MyPhoto', pid=0, desc="photos taken by myself")
        DBSession.add(my_photo_cat)
        my_note_cat = MyCat(name='MyNote', pid=0, desc="take a note a day to save life")
        DBSession.add(my_note_cat)
        my_mp3_cat = MyCat(name='MyMP3', pid=0, desc="my favorite mp3")
        DBSession.add(my_mp3_cat)
        my_video_cat = MyCat(name='MyVideo', pid=0, desc="all my hot videos")
        DBSession.add(my_video_cat)
        DBSession.flush()
        
        my_sport_photo_cat = MyCat(name='SportPhoto', pid=my_photo_cat.id, desc="photos of sports")
        DBSession.add(my_sport_photo_cat)
        my_private_photo_cat = MyCat(name='PrivatePhoto', pid=my_photo_cat.id, desc="secret photos")
        DBSession.add(my_private_photo_cat)
        DBSession.flush()
        
        afile = MyFile(name='ski.jpg', cat=my_sport_photo_cat.id, save_path="", desc="20111112 by canon")
        DBSession.add(afile)
        afile = MyFile(name='love.jpg', cat=my_private_photo_cat.id, save_path="", desc="20111111 by canon")
        DBSession.add(afile)
        afile = MyFile(name='20120327.txt', cat=my_note_cat.id, save_path="", desc="diary 20120327")
        DBSession.add(afile)
        afile = MyFile(name='paradise.mp3', cat=my_mp3_cat.id, save_path="", desc="mp3 download")
        DBSession.add(afile)
        afile = MyFile(name='hot.avi', cat=my_video_cat.id, save_path="", desc="hot video from some place")
        DBSession.add(afile)


详细代码参见:
https://github.com/eryxlee/pyramid_koans/tree/master/traverseonrdb

No comments:

Post a Comment