Hick
Hick

Reputation: 36404

How to structure a CherryPy app into a MVC architecture?

I was planning for my structure to be something similar to this:

appname/libs/user
            /football
            /tax

Where the library user, will have the models for the User, the controller which would show up the REST JSON API and the views.

The problems that I'm facing currently can be divided into two major questions, and which mainly stem from using Django for a while. I'm fairly new to CherryPy and SqlAlchemy.

  1. How to define modles in each of this library? The problem I face is I've to inherit the Base Declarative and Engine in every model and run it as a standalone app for its models to be generated. Is there a mechanism where I can plug in the libraries and the database should pull all the models and create it? (Something that Django does.)

  2. How to define routes/apis? (a urls.py)

Upvotes: 0

Views: 1585

Answers (1)

cyraxjoe
cyraxjoe

Reputation: 5741

How about defining the declarative base (sqlalchemy) in appname/db/__init__.py and for each of the libs import the base from appname in appname/libs/NAME/models.py:

import appname.db

Base = appname.db.Base    

class MyUser(Base):
    ...

To get a database session just use a scoped session for example, this could be the basic content for appname/db/__init__.py (or just db.py if you don't want to define additional base models in appname/db/models.py)

from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import engine_from_config


__all__ = ['session', 'ses']

ses = session = scoped_session(sessionmaker())

def load_engine(config):
    engine =  engine_from_config(config, prefix='')
    session.configure(bind=engine)

Then set a tool to remove the session from the thread locals when the request has ended:

import cherrypy

from appname import db

def remove_db_session():
    db.session.remove()

cherrypy.tools.removedbs = cherrypy.Tool('on_end_request', remove_db_session)

from that point forward just use the session as normal from any part of your application, for example:

from appname import db
from appname.libs.user import models

class User:
    exposed = True

    def GET(self, id):
        db.ses.query(models.User).filter_by(id=id)
        # and let the tool to remove the session
        # when the request finish

By the way to enable that removedbs tool, just make sure that you execute somewhere that cherrypy.tools.removedbs = .... I usually put that in: appname/cptools/tool and then in the config dictionary or file set tools.removedbs.on to True

Working with cherrypy means that you will build the application tree, there is no extra magic you need to have a central place to build the full tree, if you want to use the MethodDispatcher or the DefaultDispatcher.

In this case I recommend you the MethodDispatcher, and probably this post can give you a little more perspective and this is from my blog emulating the github api without any base handler.

There is an alternative to use more django like routes with the RoutesDispatcher, but you will lose a lot of functionality from the tools.

To show you an example with the MethodDispatcher and building your own object tree, from the current structure you can have a build function on the appname/builder.py and make something like this:

from appname.views import Main
from appname.libs import user, football

appmap = {'user': user,
         'footbal': football}

def build_app(*apps):
    root = Main()
    for app in apps:
       appmodule = appmap[app]
       appmodule.attach(root)
    return root

And inside the appname/libs/user/__init__.py

from appname.libs.user import views

def build_tree():
    root = views.Main()
    root.management = views.Management()
    return root

def attach(root):
     root.user = build_tree()

That's just a way to structure the application, there is also a repository with cherrypy recipes which are pretty helpful.

Upvotes: 1

Related Questions