.table 과 DB migration

포럼에 자주 나오는 질문중에 하나가 db migration과 관련된 migration_enable, migrate, fake_migrate 과 .table에 관계에 대한 내용이다. 이번에도 Niplod가 또 정리해 줬네요.

1 .table 파일
.table 파일은 migration할때만 사용된다.
2. DAL, define_table
DAL정의를 보면 다음과 같이 migration관련 인자를 볼수 있는데 migration은 기본적으로 enable된 상태이다.

__init__(self, uri='sqlite://dummy.db', ...,
migrate=True,
fake_migrate=False,
migrate_enabled=True,
fake_migrate_all=False,
...)
http://www.web2py.com/examples/static/epydoc/gluon.dal-pysrc.html#DAL.__init__

DAL이나 모든 define_table에 migrate_enabled=False or migrate=False가 설정된다면 web2py는 model 안에 테이블 선언을 (define_table) 신뢰하기 때문에 .table파일을 필요로 하지 않게 됩니다. 즉 .table파일이 있던없던 상관없다는 뜻입니다.

.table이 없는 상태에서 migrate=True인 경우에는 web2py가 .table파일을 생성합니다.

migrate이 .table파일을 기반으로 db table을 생성한다면(.table->db table) fake_migrate 은  model안의 테이블 선언(define_table)을 기준으로 .table파일을 생성하거나 갱신한다는 것입니다(define_table -> .table).

The bottomline is:

– .table files are just needed for migrations.

– If you have migrate_enabled=False or migrate=False on all tables (auth too), web2py is instructed to trust your models to be in sync with the database, so no .table files are neither created nor required.
– if you don’t have .table files and you turn migration on, if table files are not found web2py tries to create them (because if you don’t have any .table files, web2py believes that the underlying database doesn’t has them)
– fake_migrate enables a different behaviour: it creates/updates .table files according to your models without triggering any create/update on the database
Happy Coding~:)
Posted in web2py, DAL | Leave a comment

run web2py on Nitrous.io

오늘은 무료 호스팅을 지원하는 또 다른 서비스 Nitrous.io에 web2py를 설치하는 과정에 대해서 살펴보도록 하겠습니다.

#
Nitrous.io
https://www.nitrous.io/join/O-lTsWhDtns

등록은 위 URL을 이용해서 등록하세요(이거 이용하면 제 용량이 늘어나요:)
등록 과정은 어려운게 없으니 그냥 진행하시면 되고 Help에 나와 있는 내용과 약간 다른 Key 등록 과정에 대해서 먼저 설명하겠습니다.

#
SSH key 등록
SSH login을 하려면 먼저 key를 등록해야 하는데 Help에 나와 있는대로 하면 안되네요. 다음은 제가 성공한 방법 입니다.

* puttygen download
먼저 PuttyGen.exe development 버전을 다운로드 받습니다.
stable 버전은 key length가 1024인데 반해 development 버전은 2048입니다.

* KeyGen
KeyGen을 실행해서 “Generate” 선택하고 마우스 좀 움직여 주면 key가 생성됩니다.
여기서 중요한 것이 화면에 붉은 색 박스 안의 key를 복사해 뒀다 Nitrous.io에 등록해 줘야 한다는 것입니다.

bibl2be4붉은 색 박스의 key를 nitrous_key.pub라 저장하고
다음 “Save Private Key”를 선택해서 nitrous_key.ppk로 저장합니다.
* Public key 등록
Nitrous.io에 로긴 후 오른쪽 상단에 Public Keys를 선택해서 nitrous_key.pub의 내용을 복사해 넣고 등록을 완료합니다.
2rennamf
key 복사
d5bk3bv2

*
putty setting
등록한 key를 이용해서 nitrous.io에 로긴하기 위해서는 생성한 key를 putty에 설정해줘야 합니다.
Putty->설정->Connection->SSH->Auth화면에서 “Private Key file for authentication”에 생성한 private key(nitrous_key.ppk)를 선택하고 저장합니다.
yepezypu

#
Box 생성
이제 putty를 통해서 nitrous.io에 로긴한후에 Box를 생성합니다. Box는 Nitrous.io에서 제공하는 sandbox 개발 환경으로 과금에 기본단위입니다. 미니멈은 free로 제공하니 기본으로 생성하세요.
2frdmw1p

Python/Django를 선택하고 이름 및 서버 위치를 선택해서 Box를 생성합니다.
gr3vqvxm

여기서 preview url은 나중에 서버를 실행한후 사용됩니다.

#
web2py 설치
Nitrous.io에 로긴하면 workspace라는 디렉토리가 생성되어 있습니다. 여기에 web2py repository를 clone합니다.

$ cd workspace
$ git clone https://github.com/web2py/web2py.git

#
web2py 실행
Nitrous.io는 3000~9000번 사이의 포트에 서버를 실행할 수 있습니다.
web2py를 8000번 포트를 사용하도록 하고 ip를 0.0.0.0으로 지정합니다.

$ cd web2py
$ python web2py.py –a ‘000000’ –i 0.0.0.0 –p 8000

#
preview
Box생성시 주어진 Preview URL을 통해서 web2py가 정상적으로 구동되는지 확인해 본다.
https://redmind-16845.apne1.actionbox.io:8000
dy1errc5

Happy Coding~:)

Posted in hosting, python, web2py | Leave a comment

[DAL] Encrypting/decrypting db values

Web2py에서 DB에 데이터를 encrypt해서 저장하는 경우는 Password를 hashing하는 경우밖에 없다. 일반 다른 데이터를 encrypt/decrypt하고 싶은 경우는 어떻게 해야 하는가?

Nipplod의 encrypt/decrypt 구현 예시

import gluon.contrib.aes as AES
import threading 
import os
import base64

def fast_urandom16(urandom=[], locker=threading.RLock()):
    """
    this is 4x faster than calling os.urandom(16) and prevents
    the "too many files open" issue with concurrent access to os.urandom()
    """
    try:
        return urandom.pop()
    except IndexError:
        try:
            locker.acquire()
            ur = os.urandom(16 * 1024)
            urandom += [ur[i:i + 16] for i in xrange(16, 1024 * 16, 16)]
            return ur[0:16]
        finally:
            locker.release()
            
def pad(s, n=32, padchar=' '):
    return s + (32 - len(s) % 32) * padchar

def AES_new(key, IV=None):
    """ Returns an AES cipher object and random IV if None specified """
    if IV is None:
        IV = fast_urandom16()

    return AES.new(key, AES.MODE_CBC, IV), IV

def w2p_encrypt(data):
    key = 'asdsaddasdasdas'
    key = pad(key[:32])
    cipher, IV = AES_new(key)
    encrypted_data = IV + cipher.encrypt(pad(data))
    return base64.urlsafe_b64encode(encrypted_data)

def w2p_decrypt(data):
    key = 'asdsaddasdasdas'
    key = pad(key[:32])
    data = base64.urlsafe_b64decode(data)
    IV, data = data[:16], data[16:]
    cipher, _ = AES_new(key, IV=IV)
    data = cipher.decrypt(data)
    data = data.rstrip(' ')
    return data

db.define_table('t_test',
                Field('f_field')
                )

db.t_test.f_field.filter_in = lambda value : w2p_encrypt(value)
db.t_test.f_field.filter_out = lambda value : w2p_decrypt(value)

https://groups.google.com/d/msg/web2py/uGFQD0PBefQ/Zi-SPOLVSXIJ

Happy Coding~:)

Posted in DAL, python, web2py | Leave a comment

[DAL]epoch

DBMS별로 date를 다루는 방법이 다를수 있으므로 epoch를 사용해야 한다.

This may work on sqlite but I am not sure. Anyway it is not portable. It should be possible to use .epoch()

import time
query = (db.status.updated_on.epoch() + db.status.interval_time*60) < time.time()
—-

Please try:

query = Expression(db,”interval_time < (strftime(‘%M’,’now’) – strftime(‘%M’, updated_on))”)
On the page suggested by Niphlod we read:
Compute the number of seconds between two dates:
SELECT strftime(‘%s’,’now’) – strftime(‘%s’,’2004-01-01 02:34:56′);
So by replacing ‘%s’ with ‘%M’ we obtain the difference in minutes between two dates.
Posted in python, web2py | Leave a comment

framework benchmarks – web2py surprisingly slow?

어떤 한 blogger가 python web framework들간의 속도 측정을 한 결과
web2py  가 너무나 성능이 안좋게 나왔다 그에 대한 논의 진행

Just stumbled across this benchmark:

http://mindref.blogspot.pt/2012/09/python-fastest-web-framework.html

on the python group discussion:
https://groups.google.com/forum/?fromgroups=#!topic/comp.lang.python/yu1_BQZsPPc

The author also notes a memory leak problem with web2py but no specifics that I could see.

Thoughts?

https://groups.google.com/d/topic/web2py/Yrtrj3BSFl4/discussion

결론은 각 프레임웍마다 지향하는 바가 다르기 때문에 기능과 초기 설정이 서로 달라서 생기는 현상. 특별히 web2py가 느리지 않다가 결론.

Posted in python, web2py | Leave a comment

DB migration 순서

https://groups.google.com/d/msg/web2py/UTNIwi7LEJM/zuG0m2-Ki9MJ

while developing you should NOT use any of the migrate, fake_migrate, migrate_enabled, etc. Zero tickets in regards of db migrations (unless you do something weird like trying to change a column type from string to integer).

The minute you go on production, deploy the app, hit the appadmin page (so all tables are created on your fresh “production” db), return to the db.py file and set migrate=False on the DAL.
Next iteration, you develop another piece of app, freeze it, update your production, set migrate=True on the DAL, re-hit the appadmin page, return to db.py and set migrate=False.
Next iteration, you screw some table (like converting a string column to an integer), the previous working method will NOT work (mostly because only you can know how to migrate that column (others call it “fixtures”….e.g. attempt a conversion and NULL all fields that doesn’t cast to integers vs drop the column and readd and fill with default values, etc, etc, etc)). It’s time to:
– manually alter the database (optionally applying your fixtures) so that the db reflects your model
– update your app
– optional step: set fake_migrate_all=True in the DAL, hit the appadmin page (so .table files are recreated) and reset fake_migrate_all to False
– set migrate=False on the DAL
– use you app

Didn’t have ANY problems with this line of work in 2 years of deployment.

Posted in python, web2py | Leave a comment

Scaling Web2py – session.disable 구현

Anthony response
https://groups.google.com/d/msg/web2py/rO3AyoVycaU/riUyUxpZ96gJ

Massimo response
https://groups.google.com/d/msg/web2py/rO3AyoVycaU/pM7Dsa19HIUJ

Anthony가 제안한 session disable 구현
https://groups.google.com/d/msg/web2py/rO3AyoVycaU/MeEqaFxB-K4J

Posted in Uncategorized | Leave a comment