pythonmongodbmodel-view-controllerflaskmongokit

Implementing MVC in Python? (using Flask and MongoKit)


I'm coming from a spaghetti code PHP background. I'm trying to learn MVC by cutting my teeth on Python with Flask and MongoDB. I think this question could apply to other situations. It's more of a newbie Python question. But this is where I'm running into it for the first time with this setup.

I'm using Flask with Blueprints to layout my app. I'm breaking down each major site feature into a sub directory of myapp (module/blueprint). Here is my directory structure

Dir structure

/proj/config.py
/proj/runserver.py
/proj/myapp/
/proj/myapp/__init__.py
/proj/myapp/static/
/proj/myapp/templates/
/proj/myapp/templates/users/
/proj/myapp/templates/forums/
/proj/myapp/templates/frontend/
/proj/myapp/users/
/proj/myapp/users/__init__.py
/proj/myapp/users/models.py
/proj/myapp/users/views.py
/proj/myapp/forums/ ..
/proj/myapp/frontend/ ..

So I'm trying to implement this simple MongoKit example. But instead of having it in one file. I need to spread it out across the MVC pattern.

MongoKit sample

from flask import Flask, request, render_template, redirect, url_for
from flask.ext.mongokit import MongoKit, Document

app = Flask(__name__)

class User(Document):
    __collection__ = 'user'
    structure = {
        'name': unicode,
        'email': unicode,
    }
    required_fields = ['name', 'email']
    use_dot_notation = True

db = MongoKit(app)
db.register([User])

The main part of my app is in init.py and it looks like:

/myapp/_init_.py

from flask import Flask, render_template, abort
from flask.ext.mongokit import MongoKit, Document

from .home.views import mod as home_blueprint
from .users.views import mod as user_blueprint
from .forums.views import mod as forum_blueprint

def create_app():
    app = Flask(__name__)
    app.config.from_object('config')

    # Register blueprints
    app.register_blueprint(home_blueprint)
    app.register_blueprint(user_blueprint, url_prefix="/users")
    app.register_blueprint(forum_blueprint, url_prefix="/forums")

    db = MongoKit(app)

    @app.errorhandler(404)
    def not_found(error):
        return render_template('404.html')

    @app.errorhandler(500)
    def internal_error(exception):
        return "Some internal error has taken place.  Alert somebody!"

    return app

And then I'm not quite sure what to do with the rest. I setup a class in /myapp/users/models.py like below. I know the last statement isn't defined. I'm not sure if it goes there or if I need to put it someplace else. Or if it does go there, how do I get "db" from the create_app() in init.py. I figure this has less to do with MongoKit and basic Python stuff.

/myapp/users/models.py

from flask.ext.mongokit import MongoKit, Document

class User(Document):
    structure = {
    'name': unicode,
    'email': unicode,
}
    use_dot_notation = True

db.register([User])

Solution

  • If you want to use create_app function, then I would change your __init__.py to something like:

    /myapp/__init__.py

    from flask import Flask, render_template, abort
    from flask.ext.mongokit import MongoKit, Document
    
    from .home.views import mod as home_blueprint
    from .users.views import mod as user_blueprint
    from .forums.views import mod as forum_blueprint
    
    def create_app():
        app = Flask(__name__)
        app.config.from_object('config')
    
        # Register blueprints
        app.register_blueprint(home_blueprint)
        app.register_blueprint(user_blueprint, url_prefix="/users")
        app.register_blueprint(forum_blueprint, url_prefix="/forums")
    
        db = MongoKit(app)
    
        @app.errorhandler(404)
        def not_found(error):
            return render_template('404.html')
    
        @app.errorhandler(500)
        def internal_error(exception):
            return "Some internal error has taken place.  Alert somebody!"
    
        return app,db
    
    # Make sure you are calling create_app func below:
    (app,db) = create_app()
    

    Now in your models code, you can refer to db variable.

    /myapp/users/models.py

    from flask.ext.mongokit import MongoKit, Document
    
    # import db below like this
    from myapp import db
    
    class User(Document):
        structure = {
        'name': unicode,
        'email': unicode,
    }
    use_dot_notation = True
    
    # ok to do this below
    db.register([User])