Nem nướng – แหนมเนือง
Bánh canh – ข้าวเปียก / ก๋วยจั๊บ
Nem nướng – แหนมเนือง
Bánh canh – ข้าวเปียก / ก๋วยจั๊บ
ต่อจาก ติดตั้ง Django ก็ต่อด้วย Pylons. ก่อนหน้าจะพยายามลง Pylons ผมก็ลองพวก WSGIDaemonProcess ไปแล้ว แต่ว่าไม่สำเร็จก็เลยข้ามๆ ไป. ใช้ user เป็น www-data ก็ได้
.
Pylons ก็มา pattern เดิมๆ ที่อ่านมาจาก http://code.google.com/p/modwsgi/wiki/IntegrationWithPylons เริ่มด้วยสร้าง pylons.wsgi ใน /home/veer/public_html/wsgi-scripts ตามนี้
APP_CONFIG = "/home/veer/Develop/pylons/mydb4/production.ini"
import os
os.environ['PYTHON_EGG_CACHE'] = "/home/veer/egg"
import sys
sys.path.append("/home/veer/Develop/pylons/mydb4")
from paste.deploy import loadapp
application = loadapp("config:" + APP_CONFIG)
แล้วก็สร้าง /home/veer/egg เปลี่ยน permission ( mkdir /home/veer/egg; chmod 777 /home/veer/egg )
แล้วก็แก้สร้าง production.ini โดยการ copy มาจาก development.ini แล้วก็แก้ให้
full_stack = false
และ
debug = false
เท่านี้ก็น่าจะพอใช้ได้แล้ว
ลืมไปผมสร้าง app ไว้ใน /home/veer/Develop/mydb4 นะครับ พวก development.ini ก็อยู่ในนี้ล่ะ
หลังจากที่ได้ word list จาก au8ust มาผมก็ยังไม่ได้ทำอะไรกับ word list เลย. แต่เท่าที่ดูแล้วโปรแกรมที่แก้แล้วน่าจะมีประโยชน์กับหลายๆโปรแกรมน่าจะเป็น icu. อย่างเช่น OpenOffice.org เป็นต้น (แต่ก็ไม่รู้ว่าจริงหรือเปล่า)
หลังจากที่ดูคร่าวๆ แล้วไฟล์แรกที่น่าจะต้องแก้น่าจะเป็น source/common/dictbe.h ที่ในนั้นมี ThaiBreakEngine อยู่ ก็เลยคิดว่าก็คงต้องมี LaoBreakEngine ด้วยเหมือนกัน แก้กฎข้างในเล็กๆ น้อยๆ พวกไม้ยมก ก็คงจะไม่เหมือนกันหรือเปล่า … อันนี้ก็ไปแก้ใน source/common/dictbe.cpp
ตอนนี้แผนต่อไปก็คงต้องลงมือทำดูพร้อมเขียน test อะไรประมาณนั้น
ป.ล. libthai ก็ดูน่าสนใจดี มีใช้หลายโปรแกรมเหมือนกัน แต่ libthai ตัดคำภาษาลาวด้วยก็ดูแปลกๆ หรือเปล่า?
แน่นอนเป็นภาคต่อมาจาก Turbogears + userdir + mod_wsgi. Django ก็ใช้ท่าคล้ายๆ Turbogears เปลี่ยน prefix นิดๆ หน่อยก็ใช้ได้แล้ว
หลังจากศึกษาวิธีใช้จาก http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango ผมสร้าง django.wsgi ไว้ใน /home/veer/public_html/wsgi-scrips อีกเช่นเคย
import os, sys
sys.path.append('/home/veer/Develop/django/mysite') # site ของผมเก็บไว้ที่นี้
sys.path.append('/home/veer/Develop/django')
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
ที่ลำบากนิดหน่อยคือพวก media ทั้งหลาย ผมก็ copy มาไว้ใน home เลย (ขนาดประมาณ 300KiB กว่าๆ)
cp -r /usr/share/python-support/python-django/django/contrib/admin/media/ /home/veer/public_html/django_admin_media
แล้วก็ไปแก้ settings.py ใน /home/veer/Develop/django/mysite นิดหน่อย แก้ ADMIN_MEDIA_PREFIX จากเท่ากับ ” เป็น ADMIN_MEDIA_PREFIX = ‘/~veer/django_admin_media/’
เท่านี้ก็ไปเปิดเว็บดูก็ใช้ได้ (ถ้าผมไม่ได้ลืมเขียนอะไรไปนะ)
พรุ่งนี้น่าจะได้ลอง Pylons กับ WSGIDaemonProcess username user=username อะไรทำนองนี้.
อาจจะดูคลั่งๆ หน่อยแต่ mod_wsgi + userdir + Turbogears ก็ใช้ได้แล้ว. ด้วยพื้นฐานจากการใช้ mod_wsgi+userdir , การใช้ mod_wsgi กับ Turbogears และ การใช้ mod_wsgi กับ Turbogears แบบ non-root-mount. ก็แทบจะไม่ต้องทำอะไรแล้ว
.
แค่ copy ไฟล์ tg.wsgi ที่เคยอยู่ใน /home/veer/tg/tgapp/apache ไปไว้ใน /home/veer/public_html/wsgi-scripts/ แล้วก็แก้ prod.cfg ใน /home/veer/tg/tgapp นิดหน่อยที่ server.webpath ให้เปลี่ยนเป็น server.webpath=”/~veer/wsgi-scripts/tg.wsgi” เท่านี้ก็ใช้ซะงั้น.
สำหรับ Turbogears แล้วสำคัญมาที่ต้องใช้ tg.url เวลาเขียน URL ไม่ใส่ URL เอาเองตรงๆ (แบบที่ผมเคยทำ) … ไม่งั้นเวลามา deploy แบบนี้ก็แก้กันอ้วก
.
วิธีทำจริงๆ ก็อ่านจาก http://www.lucasmanual.com/mywiki/TurboGears#head-57ee578707aa057229eb1171a8e4aeb553bd6d3a มาเกือบหมด. แต่ว่าเขียนเสียหน่อยเพื่อความต่อเนื่องจากที่เขียนไว้เดิม. เริ่มจากแก้ /home/veer/tg/tgapp/apache/tg.wsgi:
import sys
sys.path.append('/home/veer/tg/tgapp')
sys.stdout = sys.stderr
import os
os.environ['PYTHON_EGG_CACHE'] = '/home/veer/tg/python-eggs'
import atexit
import cherrypy
import cherrypy._cpwsgi
import turbogears
# ข้างล่างเปลี่ยนไปใช้ fullpath แทนที่จะเขียน prod.cfg หรือ dev.cfg เฉยๆ
turbogears.update_config(configfile="/home/veer/tg/tgapp/prod.cfg", modulename="tgapp.config")
turbogears.config.update({'global': {'server.environment': 'production'}})
turbogears.config.update({'global': {'autoreload.on': False}})
turbogears.config.update({'global': {'server.log_to_screen': False}})
import tgapp.controllers
cherrypy.root = tgapp.controllers.Root()
if cherrypy.server.state == 0:
atexit.register(cherrypy.server.stop)
cherrypy.server.start(init_only=True, server_class=None)
application = cherrypy._cpwsgi.wsgiApp
จริงๆ แล้วก็แก้บรรทัดเดียว
… แต่ตอนลองทำงงเหมือนกัน
แล้วก็ไปสร้าง server.log ใน /home/veer/tg/tgapp/server.log อันนี้มีก็ทำแบบชั่วคราวๆ
(อีกแล้ว)
(อยู่ใน /home/veer/tg/tgapp) touch server.log chmod 777 server.log
ตามด้วยแก้ /home/veer/tg/tgapp/prod.cfg ทีแรกมันไม่มีให้แก้ก็เลยต้อง copy sample-prod.cfg มา
เพิ่ม server.webpath=”/first” เข้าไป (จริงมี # server.webpath=”" อยู่แล้ว ก็แค่เอา shape ออกแล้วใส่ /first ลงไป) แก้ path ของ server.log แบบนี้ args=”(‘/home/veer/tg/tgapp/server.log’,)” จากที่เดิมเขียนไว้ว่า args=”(‘server.log’,)”
ตามด้วยแก้ /etc/apache2/mod-enabled/mod-wsgi.conf เดิมเขียนไว้ว่า
WSGIScriptAlias / /home/veer/tg/tgapp/apache/tg.wsgi
ก็แก้เป็น
WSGIScriptAlias /first /home/veer/tg/tgapp/apache/tg.wsgi
เพื่อเปลี่ยนที่ mount
แล้วก็ restart apache ( /etc/init.d/apache restart ) จากนั้นพอเข้าไปดูใน localhost/first ก็ได้ผลตามต้องการ
… ต่อไปก็เป็น userdir T_T (เหมือนหา doc ไม่ค่อยเจอด้วย
)
วิธีลงอ่านมาจาก http://code.google.com/p/modwsgi/wiki/IntegrationWithTurboGears. ที่เขียนนี้ผมยังไม่ได้ลองใช้ userdir เลย คิดว่าน่าจะซับซ้อนขึ้นมาก. จริงๆ แล้วแค่เปลี่ยน url จาก localhost ไปเป็น localhost/tg ก็เจ๊งแล้ว
.
เริ่มจากแก้ไฟล์ /etc/apache2/mod_enabled/mod-wsgi.conf:
<IfModule mod_wsgi.c>
WSGIScriptAlias / /home/veer/tg/tgapp/apache/tg.wsgi
<Directory /home/veer/tg/tgapp/apache>
Order deny,allow
Allow from all
</Directory>
</IfModule>
เสร็จแล้วก็สร้าง folder ชื่อ /home/vee/tg (mkdir /home/veer/tg) แล้วก็สร้าง python-eggs ใน /home/veer/tg ไว้เป็น cache แล้วผมก็เปลี่ยน permission ของ python-eggs เป็น 777 เลย เพราะว่า user id ของ folder กับ apache ต่างกัน … จริงๆน่าจะมีวิธีแก้ที่ดีกว่านี้ แต่ผมคิดว่าเอาง่ายให้ได้ก่อนดีกว่า
จากนั้นใน /home/veer/tg ก็เรียก tg-admin quickstart tgapp ตอบๆ อะไรไปหน่อยก็จะได้ folder ชื่อ /home/veer/tg/tgapp ขึ้นมา ในนั้นก็สร้าง /home/veer/tg/tgppp/apache/tg.wsgi ขึ้นมา ข้างในก็ลองมาตามตัวอย่างเลย แต่ก็แอบแก้ path กับชื่อ project นิดหน่อย
import sys
sys.path.append('/home/veer/tg/tgapp')
sys.stdout = sys.stderr
import os
os.environ['PYTHON_EGG_CACHE'] = '/home/veer/tg/python-eggs'
import atexit
import cherrypy
import cherrypy._cpwsgi
import turbogears
turbogears.update_config(configfile="dev.cfg", modulename="tgapp.config")
turbogears.config.update({'global': {'server.environment': 'production'}})
turbogears.config.update({'global': {'autoreload.on': False}})
turbogears.config.update({'global': {'server.log_to_screen': False}})
import tgapp.controllers
cherrypy.root = tgapp.controllers.Root()
if cherrypy.server.state == 0:
atexit.register(cherrypy.server.stop)
cherrypy.server.start(init_only=True, server_class=None)
application = cherrypy._cpwsgi.wsgiApp
เสร็จแล้วก็ restart apache ( sudo /etc/init.d/apache2 restart ) แล้วก็เปิดเว็บดูที่ localhost ก็ดูได้ตามรูป
แต่ว่าก็ยังเหลืออะไรที่ต้องแก้อีกมากมาย พื้นก็เปลี่ยน url จาก localhost ไปเป็น localhost/tgapp ผมก็ยังทำไม่ได้เลย
ผมอ่านเรื่องเปิดเทียบ web app tech ต่างๆ มา. เห้น mod_wsgi น่าสนใจดีก็เลยจะลองเล่นบ้าง (เอาแบบให้ใช้ได้หลายๆ user ด้วย น่าจะเหมาะกับ lab ดี) ก็เริ่มจากไปอ่าน http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines
แต่ก่อนจะทำตามตำรา ผมก็ลง mod_wsgi ก่อนเลย
sudo aptitude install libapache2-mod-wsgi
ตามด้วย enable มันซะ
sudo a2enmod mod-wsgi
แปลกนะมีคำว่า mod ติดมาด้วย หาตั้งนาน
ปกติเวลาจะใช้ mod_userdir ก็แค่
sudo a2enmod userdir
(ไม่ใช่เหรอ? …. รวมถึง mod_rewrite และอื่นๆ ด้วย)
ด้วยความพิเศษของ Ubuntu/Debian นิดหน่อยๆ ไฟล์ที่ผมเข้าไปแก้คือ /etc/apache2/mods-enabled/userdir.conf ก็ดัดแปลงตามตัวอย่างอะนะแก้แล้วเป็นแบบนี้
<IfModule mod_userdir.c>
UserDir public_html
UserDir disabled root
<Directory /home/*/public_html/>
AllowOverride FileInfo AuthConfig Limit
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
</Directory>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/~([^/]+)
RewriteRule . - [E=APPLICATION_GROUP:~%1]
<Directory /home/*/public_html/wsgi-scripts/>
Options ExecCGI
SetHandler wsgi-script
WSGIApplicationGroup %{ENV:APPLICATION_GROUP}
</Directory>
</IfModule>
เสร็จแล้วผมก็เข้าไปสร้าง folder ที่ /home/veer/public_html/wsgi-scripts พร้องเปลี่ยน permission เป็น 755 ตามด้วยเอา myapp.wsgi ตามตัวอย่างไปวางในนั้น
def application(environ, start_response):
status = '200 OK'
output = 'Hello World!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
จากนั้นก็ไปที่ web browser เรียก http://127.0.0.1/~vee/wsgi-scripts/myapp.wsgi (ตามรูป)
ขั้นตอนถัดไปก็จะลองลง Pylons และ Django ดู
I use Pylons and Elixir from trunk (both). Paster create -t pylons … generate most of code for SQLAlchemy so in order to use Elixir, I just made small modification following http://cleverdevil.org/computing/68/ and http://elixir.ematia.de/trac/wiki/TutorialDivingIn. In the example, meta.py has not been modified but I try to modify meta.py too. Also I put a lot of thing in function “init_model”. I don’t know whether these will casue problems … but as least, it works with a small example
.
In my example, the project name is “mydb4″. Firstly, I modified mydb4/model/meta.py:
engine = None
Secondly, mydb4/model/__init__.py was modfied. In this file, I put also the class Person, which declares the table in the database.
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.orm import scoped_session, sessionmaker
import meta
import elixir
from unlalign.model import meta
sm = orm.sessionmaker(autoflush=True, autocommit=True)
meta.Session = orm.scoped_session(sm)
elixir.session = meta.Session
elixir.options_defaults.update({ 'shortnames': True })
def init_model(engine):
meta.engine = engine
elixir.metadata.bind = engine
from elixir import *
class Person(Entity):
name = Field(String(100))
elixir.setup_all()
mydb4/websetup.py has been edited also:
"""Setup the mydb4 application"""
import logging
from mydb4.config.environment import load_environment
log = logging.getLogger(__name__)
def setup_app(command, conf, vars):
"""Place any commands to setup mydb4 here"""
load_environment(conf.global_conf, conf.local_conf)
# Load the models
from elixir import metadata
from mydb4.model import meta
metadata.bind = meta.engine
# Create the tables if they aren't there already
metadata.create_all(checkfirst=True)
The controller (mydb4/controller/person.py) looks like below:
import logging
from pylons import request, response, session
from pylons import tmpl_context as c
from pylons.controllers.util import abort, redirect_to
from mydb4.lib.base import BaseController
import mydb4.model as model
log = logging.getLogger(__name__)
class PersonController(BaseController):
def index(self):
# Return a rendered template
# return render('/template.mako')
# or, Return a response
return ",".join([i.name for i in model.Person.query.all()])
We have to modify also mydb4/lib/base.py
"""The base Controller API
Provides the BaseController class for subclassing.
"""
from pylons.controllers import WSGIController
from pylons.templating import render_mako as render
from mydb4.model import meta
import elixir
class BaseController(WSGIController):
def __call__(self, environ, start_response):
"""Invoke the Controller"""
# WSGIController.__call__ dispatches to the Controller method
# the request is routed to. This routing information is
# available in environ['pylons.routes_dict']
try:
return WSGIController.__call__(self, environ, start_response)
finally:
elixir.session.remove()
At the shell, command “paster setup-app development.ini” was called, then it created database correctly. After database was created, data are insert into table manually by “sqlite3 development.db” … then
insert into mydb4_model_person(id,name) values (1, "titi"); insert into mydb4_model_person(id,name) values (2, "tata");
After running “paster serve –reload development.ini”, then visit the url “http://localhost:5000/person/index”, it looks like this screen capture below: