วันศุกร์ที่ 22 กันยายน พ.ศ. 2560

Turbogears 2.3 on Heroku

Turbogears 2.3 on Heroku

Step 1 : Install waitress
pip install waitress


Step 2 : Install turbogears app
gearbox quickstart myproturbo


Step 3 : Change to project
cd myproturbo


Step 4 : Create file requirements.txt  in project
pip freeze > requirements.txt
 *** Open file requirements.txt and delete your project which you setup in python environment ex:

myproturbo=0.1  [your project: setup.py develop]
or
-e git+https://github.com/xxxxxxxxx#egg=xxxx  [your project: from git or subversion]


Step 5 : Add -e . in last row in file  requirements.txt

alembic==0.9.5
babel==2.5.1
backlash==0.1.2
beaker==1.9.0
crank==0.8.1
decorator==4.1.2
formencode==2.0.0a1
funcsigs==1.0.2
gearbox==0.1.1
kajiki==0.7.1
mako==1.0.7
MarkupSafe==1.0
nine==1.0.0
PasteDeploy==1.5.2
Pygments==2.2.0
python-dateutil==2.6.1
python-editor==1.0.3
pytz==2017.2
repoze.lru==0.7
repoze.who==2.3
six==1.11.0
speaklater==1.3
sprox==0.10.2
sqlalchemy==1.2.0b2
Tempita==0.5.2
tg.devtools==2.3.11
tgext.admin==0.7.4
tgext.crud==0.8.2
tgext.debugbar==0.3.0
transaction==2.1.2
TurboGears2==2.3.11
tw2.core==2.2.4
tw2.forms==2.2.5
waitress==1.0.2
webhelpers2==2.0
WebOb==1.7.3
WebTest==1.4.3
zope.interface==4.4.2
zope.sqlalchemy==0.7.7
-e .


Step 6 : copy development.ini to production.ini
cp  development.ini production.ini


Step 7 : change  config file in production.ini
[server:main]
use = egg:gearbox#wsgiref
host = 0.0.0.0
port = 8080

Change to

[server:main]
use = egg:waitress#main
host = 0.0.0.0
get port = heroku_port



Step 8 :  Generate file Procfile to start app

echo "web: /app/.heroku/python/bin/gearbox serve --debug -c production.ini heroku_port=$PORT" > Procfile

*** file name is Case-sensitive


Step 9 : Prepaire and Setup git repo
wget -O .gitignore https://raw.github.com/github/gitignore/master/TurboGears2.gitignore
git init
git add .
git commit -m "initial commit"


Step 10 : Initialize keroku project
heroku create myproturbo


Step 11 : Deploy to heroku
git push heroku master

remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
remote: -----> Installing requirements with pip
remote:        Obtaining file:///tmp/build_c1da74e071cabdd181483ce0164e3a85 (from -r /tmp/build_c1da74e071cabdd181483ce0164e3a85/requirements.txt (line 40))
remote:        Installing collected packages: myproject
remote:          Running setup.py develop for myproject
remote:        Successfully installed myproject
remote:
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing...
remote:        Done: 55.7M
remote: -----> Launching...
remote:        Released v7
remote:        https://myproturbo.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/myproturbo.git
   8b92553..d19a8fa  master -> master


Step 12 : Check status heroku
heroku logs -t


You can see : https://myproturbo.herokuapp.com/
My github :  https://github.com/tongpa/myproject.git

turbogear : http://turbogears.readthedocs.io/en/latest/cookbook/deploy/heroku.html




วันพฤหัสบดีที่ 20 เมษายน พ.ศ. 2560

Turbogears2 Change The Way Your App Loads The Database Engines


Step by Step
1. In configuration file (development.ini). I change sqlalchemy


#sqlalchemy.url = sqlite:///%(here)s/devdata.db
sqlalchemy.first.url = sqlite:///%(here)s/database_1.db
sqlalchemy.second.url = sqlite:///%(here)s/database_2.db


2. In Application Configuration to load the multiple databases. In file ../config/app_cfg.py


# make sure these imports are added to the top
from tg.configuration import AppConfig, config
from myapp.model import init_model

# add this before base_config =
class MultiDBAppConfig(AppConfig): 
    def _setup_sqlalchemy(self, conf):
    #def setup_sqlalchemy(self):
        """Setup SQLAlchemy database engine(s)"""
        from sqlalchemy import engine_from_config
        engine1 = engine_from_config(config, 'sqlalchemy.first.')
        engine2 = engine_from_config(config, 'sqlalchemy.second.')
        # engine1 should be assigned to sa_engine as well as your first engine's name
        config['tg.app_globals'].sa_engine = engine1
        config['tg.app_globals'].sa_engine_first = engine1
        config['tg.app_globals'].sa_engine_second = engine2
        # Pass the engines to init_model, to be able to introspect tables
        init_model(engine1, engine2)

#base_config = AppConfig()
base_config = MultiDBAppConfig()

In document Turbogears2 it used def setup_sqlalchemy(self): , when server start will error.
change to def _setup_sqlalchemy(self, conf): ,  server start will not error.

3. Update your model's __init__ to handle multiple Sessions and Metadata. Add maker2, DBSession2, DeclarativeBase2 and metadata2. Change function init_model in file ../model/__init__.py



# after the first maker/DBSession assignment, add a 2nd one
maker2 = sessionmaker(autoflush=True, autocommit=False,
                     extension=ZopeTransactionExtension())
DBSession2 = scoped_session(maker2)

# after the first DeclarativeBase assignment, add a 2nd one
DeclarativeBase2 = declarative_base()

# uncomment the metadata2 line and assign it to DeclarativeBase2.metadata
metadata2 = DeclarativeBase2.metadata

# finally, modify the init_model method to allow both engines to be passed (see previous step)
# and assign the sessions and metadata to each engine
def init_model(engine1, engine2):
    """Call me before using any of the tables or classes in the model."""

    #DBSession.configure(bind=engine)
    DBSession.configure(bind=engine1)
    DBSession2.configure(bind=engine2)

    metadata.bind = engine1
    metadata2.bind = engine2


4. Tell Your Models Which Engine To Use
     4.1 use engine1. create file ../model/spam.py . when query data use DBSession for database_1.db.


from sqlalchemy import Table, ForeignKey, Column
from sqlalchemy.types import Integer, Unicode, Boolean
from myapp.model import DeclarativeBase, DBSession

class Spam(DeclarativeBase):
    __tablename__ = 'spam'

    def __init__(self, id, variety):
        self.id = id
        self.variety = variety

    id = Column(Integer, autoincrement=True, primary_key=True)
    variety = Column(Unicode(50), nullable=False)
 
    @classmethod
    def selectAll(cls):
        return DBSession.query(cls).all(); 


     4.2 use engine2. create file ../model/eggs.py. when query data use DBSession2 for database_2.db.


from sqlalchemy import Table, ForeignKey, Column
from sqlalchemy.types import Integer, Unicode, Boolean
from myapp.model import DeclarativeBase2, DBSession2

class Eggs(DeclarativeBase2):
    __tablename__ = 'eggs'

    def __init__(self, id, pkg_qty):
        self.id = id
        self.pkg_qty = pkg_qty

    id = Column(Integer, autoincrement=True, primary_key=True)
    pkg_qty = Column(Integer, default=12)
 
    @classmethod
    def selectAll(cls):
        return DBSession2.query(cls).all();  




I read at http://turbogears.readthedocs.io/en/latest/cookbook/multiple-databases.html#change-the-way-your-app-loads-the-database-engines

วันอาทิตย์ที่ 19 มีนาคม พ.ศ. 2560

Turbogears 2 used kajiki template (xhtml to html)

I used Turbogears 2.4 and update to Turbogears 2.8 (Default kajiki template). I want to change Genshi to Kajiki template. I found than I change html to xhtml for kajiki templates. So I don't change It. I search Turbogears Document, In development.ini file 

#config change default extension of kajiki(.xhtml) to .html
templating.kajiki.template_extension = .html


and change base_config.renderes in  app_cfg.py

# Set the default renderer
base_config.renderers.append('kajiki')
# Set the default renderer
base_config.default_renderer = 'kajiki'


But It's not easy, In HTML file I want to change kajiki format. I read it http://turbogears.readthedocs.io/en/latest/turbogears/kajiki-xml-templates.html 

Turbogears 2.3 on Heroku

Turbogears 2.3 on Heroku Step 1 : Install waitress pip install waitress Step 2 : Install turbogears app gearbox quickstart myproturb...