librelist archives

« back to archive

How to use SQLAlchemy DB model from models.py in external python script?

How to use SQLAlchemy DB model from models.py in external python script?

From:
Alex
Date:
2011-02-23 @ 23:11
Hello,

I'm trying to use SQLAlchemy DB model in the external python script like
this:


=========== migratedb.py =======================
from migrate.versioning.util import load_model
from migrate.versioning import genmodel, schemadiff, schema
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy
import losebit
from losebit.models import db

meta = db.metadata
engine = db.engine

try:
    # managed upgrades
    cschema = schema.ControlledSchema.create(engine, 'db_migrations')
    cschema.update_db_from_model(meta)
except Exception, e:
    # unmanaged upgrades
    diff = schemadiff.getDiffOfModelAgainstDatabase(meta, engine,
excludeTables=None)
    genmodel.ModelGenerator(diff, engine).applyModel()
======================================================

For some reason db variable here is not initialized here with my DB model
for some reason, I don't know how to initialize it right and this is the
problem.
When I copy-paste my model definition to migratedb.py it works fine, but
when I do just "from losebit.models import db" It has no effect and I'm
getting:

================================
(env) C:\Users\Alex\Workspace\Python\flask>python migratedb.py
Traceback (most recent call last):
  File "migratedb.py", line 19, in <module>
    engine = db.engine
  File
"C:\Users\Alex\Workspace\Python\flask\env\lib\site-packages\flaskext\sqla
lchemy.py", line 460, in engine
    raise RuntimeError('application not registered on db '
RuntimeError: application not registered on db instance and no application
bound
================================

What do I do wrong?

My app structure is:
flask
``migratedb.py
``runserver.py
``losebit
````__init.py__
````models.py



And when I copy paste all model definition to migratedb.py:

========== migratedb.py ==================
from migrate.versioning.util import load_model
from migrate.versioning import genmodel, schemadiff, schema
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy
from losebit.models import *

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.sqlite'

db = SQLAlchemy(app)

meta = db.metadata
engine = db.engine

class Product(db.Model):
    __tablename__ = 'products'
    id = db.Column(db.Integer, primary_key=True)
    slug = db.Column(db.String(255), nullable=False, unique=True)
    name = db.Column(db.String(255), nullable=False, unique=True)

try:
    # managed upgrades
    cschema = schema.ControlledSchema.create(engine, 'db_migrations')
    cschema.update_db_from_model(meta)
except Exception, e:
    print(e)
    # unmanaged upgrades
    diff = schemadiff.getDiffOfModelAgainstDatabase(meta, engine,
excludeTables=None)
    genmodel.ModelGenerator(diff, engine).applyModel()
================================

Then it works fine, but I want just to import the model from "models.py" not
to copy-paste it, how to do it?

My other files:

========== losbit/__init__.py==========
# -*- coding: utf-8 -*-
from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy
from losebit.views.frontend import frontend
from losebit.views.admin import admin
from models import db

app = Flask(__name__)
db.init_app(app)

app.register_module(admin, url_prefix='/admin')
app.register_module(frontend)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.sqlite'
#db = SQLAlchemy(app)
=================================

and

==========losebit/models.py==========
# -*- coding: utf-8 -*-
from flaskext.sqlalchemy import SQLAlchemy
from datetime import datetime
from sqlalchemy import Table, Column, Integer, Unicode, ForeignKey, DateTime
from sqlalchemy.orm import mapper, relationship
from sqlalchemy.sql.expression import *

db = SQLAlchemy()

class Product(db.Model):
    __tablename__ = 'products'
    id = db.Column(db.Integer, primary_key=True)
    slug = db.Column(db.String(255), nullable=False, unique=True)
    name = db.Column(db.String(255), nullable=False, unique=True)
================================

Looks like I miss something simple with import and model initialization, can
you point how to do it right?

Thanks,
Alex

Re: [flask] How to use SQLAlchemy DB model from models.py in external python script?

From:
Lucas Hrabovsky
Date:
2011-02-25 @ 03:12
So say you have a models.py that looks like this:

from flask import current_app
from flaskext.sqlalchemy import SQLAlchemy
db = SQLAlchemy(current_app) #<--- Take note

meta = db.metadata
engine = db.engine

class Product(db.Model):
    __tablename__ = 'products'
    id = db.Column(db.Integer, primary_key=True)
    slug = db.Column(db.String(255), nullable=False, unique=True)
    name = db.Column(db.String(255), nullable=False, unique=True)

`current_app` will be your app if there is a request context.  You have two
ways to make sure you have a request context and you dont get a nasty error.
 One is the official way using app.test_request_context() as a context
manager:

from migrate.versioning.util import load_model
from migrate.versioning import genmodel, schemadiff, schema
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base

from app import app
with app.test_request_context():

    from models import meta, db, engine, Product

    try:
        # managed upgrades
        cschema = schema.ControlledSchema.create(engine, 'db_migrations')
        cschema.update_db_from_model(meta)
    except Exception, e:
        print(e)
        # unmanaged upgrades
        diff = schemadiff.getDiffOfModelAgainstDatabase(meta, engine,
excludeTables=None)
        genmodel.ModelGenerator(diff, engine).applyModel()



The other is kind of a hack i just made up that does something similar in
that its by no means a real request context but makes shit work in
standalone mode.  Say you have an app.py that looks like this:

from flask import Flask, request, jsonify, render_template, make_response

def make_standalone(self):
    """Monkey patch so that we can have standalone scripts that dont
    really need a request context, but have underlying modules which
    rely on current_app as the primary use case."""
    from werkzeug import create_environ
    ctx = app.request_context(create_environ())
    ctx.push()
Flask.make_standalone = make_standalone

app = Flask('flaskysqla')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.sqlite'

@app.route('/')
def index():
    return render_template('index.html')


And then your migratedb looks like:

from migrate.versioning.util import load_model
from migrate.versioning import genmodel, schemadiff, schema
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base

from app import app
app.make_standalone() # <-- Use our BS request context.
from models import meta, db, engine, Product

try:
    # managed upgrades
    cschema = schema.ControlledSchema.create(engine, 'db_migrations')
    cschema.update_db_from_model(meta)
except Exception, e:
    print(e)
    # unmanaged upgrades
    diff = schemadiff.getDiffOfModelAgainstDatabase(meta, engine,
excludeTables=None)
    genmodel.ModelGenerator(diff, engine).applyModel()


No context managers!

-Lucas

On Wed, Feb 23, 2011 at 6:11 PM, Alex <personxxl@gmail.com> wrote:

> Hello,
>
> I'm trying to use SQLAlchemy DB model in the external python script like
> this:
>
>
> =========== migratedb.py =======================
> from migrate.versioning.util import load_model
> from migrate.versioning import genmodel, schemadiff, schema
> from sqlalchemy import create_engine
> from sqlalchemy.ext.declarative import declarative_base
> from flask import Flask
> from flaskext.sqlalchemy import SQLAlchemy
> import losebit
> from losebit.models import db
>
> meta = db.metadata
> engine = db.engine
>
> try:
>     # managed upgrades
>     cschema = schema.ControlledSchema.create(engine, 'db_migrations')
>     cschema.update_db_from_model(meta)
> except Exception, e:
>     # unmanaged upgrades
>     diff = schemadiff.getDiffOfModelAgainstDatabase(meta, engine,
> excludeTables=None)
>     genmodel.ModelGenerator(diff, engine).applyModel()
> ======================================================
>
> For some reason db variable here is not initialized here with my DB model
> for some reason, I don't know how to initialize it right and this is the
> problem.
> When I copy-paste my model definition to migratedb.py it works fine, but
> when I do just "from losebit.models import db" It has no effect and I'm
> getting:
>
> ================================
> (env) C:\Users\Alex\Workspace\Python\flask>python migratedb.py
> Traceback (most recent call last):
>   File "migratedb.py", line 19, in <module>
>     engine = db.engine
>   File
> "C:\Users\Alex\Workspace\Python\flask\env\lib\site-packages\flaskext\sqla
> lchemy.py", line 460, in engine
>     raise RuntimeError('application not registered on db '
> RuntimeError: application not registered on db instance and no application
> bound
> ================================
>
> What do I do wrong?
>
> My app structure is:
> flask
> ``migratedb.py
> ``runserver.py
> ``losebit
> ````__init.py__
> ````models.py
>
>
>
> And when I copy paste all model definition to migratedb.py:
>
> ========== migratedb.py ==================
> from migrate.versioning.util import load_model
> from migrate.versioning import genmodel, schemadiff, schema
> from sqlalchemy import create_engine
> from sqlalchemy.ext.declarative import declarative_base
> from flask import Flask
> from flaskext.sqlalchemy import SQLAlchemy
> from losebit.models import *
>
> app = Flask(__name__)
> app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.sqlite'
>
> db = SQLAlchemy(app)
>
> meta = db.metadata
> engine = db.engine
>
> class Product(db.Model):
>     __tablename__ = 'products'
>     id = db.Column(db.Integer, primary_key=True)
>     slug = db.Column(db.String(255), nullable=False, unique=True)
>     name = db.Column(db.String(255), nullable=False, unique=True)
>
> try:
>     # managed upgrades
>     cschema = schema.ControlledSchema.create(engine, 'db_migrations')
>     cschema.update_db_from_model(meta)
> except Exception, e:
>     print(e)
>     # unmanaged upgrades
>     diff = schemadiff.getDiffOfModelAgainstDatabase(meta, engine,
> excludeTables=None)
>     genmodel.ModelGenerator(diff, engine).applyModel()
> ================================
>
> Then it works fine, but I want just to import the model from "models.py"
> not to copy-paste it, how to do it?
>
> My other files:
>
> ========== losbit/__init__.py==========
> # -*- coding: utf-8 -*-
> from flask import Flask
> from flaskext.sqlalchemy import SQLAlchemy
> from losebit.views.frontend import frontend
> from losebit.views.admin import admin
> from models import db
>
> app = Flask(__name__)
> db.init_app(app)
>
> app.register_module(admin, url_prefix='/admin')
> app.register_module(frontend)
>
> app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.sqlite'
> #db = SQLAlchemy(app)
> =================================
>
> and
>
> ==========losebit/models.py==========
> # -*- coding: utf-8 -*-
> from flaskext.sqlalchemy import SQLAlchemy
> from datetime import datetime
> from sqlalchemy import Table, Column, Integer, Unicode, ForeignKey,
> DateTime
> from sqlalchemy.orm import mapper, relationship
> from sqlalchemy.sql.expression import *
>
> db = SQLAlchemy()
>
> class Product(db.Model):
>     __tablename__ = 'products'
>     id = db.Column(db.Integer, primary_key=True)
>     slug = db.Column(db.String(255), nullable=False, unique=True)
>     name = db.Column(db.String(255), nullable=False, unique=True)
> ================================
>
> Looks like I miss something simple with import and model initialization,
> can you point how to do it right?
>
> Thanks,
> Alex
>