Showing posts with label web. Show all posts
Showing posts with label web. Show all posts

Saturday, June 4, 2011

web.py, mod_wsgi , RHEL6

web.py can be run in a production environment on RHEL6 with mod_wsgi using stock packages from yum with the exception of web.py itself (which can be inserted into the system Python library).

1. Install the packages that RHEL6 provides:

 yum install httpd mod_ssl mod_wsgi mysql-devel MySQL-python 

2. Insert web.py directly into RHEL's python2.6 site-packages:

cd /tmp
wget http://pypi.python.org/packages/source/w/web.py/web.py-0.35.tar.gz
tar xzf web.py-0.35.tar.gz
cd /usr/lib/python2.6/site-packages
mv /tmp/web.py-0.35/web .

3. Configure a place to host your application:

mkdir /var/www/myapp

4. Install some basic code in /var/www/myapp/code.py

import web
urls = (
        '/.*', 'hello',
        )
class hello:
        def GET(self):
                return "Hello World"
application = web.application(urls, globals()).wsgifunc()

5. Configure mod_wsgi directives for Apache in /etc/httpd/conf.d/wsgi.conf:

LoadModule wsgi_module modules/mod_wsgi.so
WSGIScriptAlias /myapp /var/www/myapp/code.py/
<Directory /var/www/tentacle/>
  Order allow,deny
  Allow from all
</Directory>

When configuring the above I used the webpy.org cookbook as a reference. Note that my previous example was development only.

web.py

I tried web.py.

I like it because it's simple and I found it intuitive and easy to learn. You can set it up quickly on Fedora with:

yum install python-webpy
yum install MySQL-python 
It was straight forward to follow the tutorial, except it's not obvious in the tutorial how to specify a different DB server besides the default localhost. The keyword argument is 'host' just like in MySQLdb.connect(), which is provided by the Python package MySQLdb; i.e. the MySQL-python yum package. Here's the example from the tutorial in which an external DB server is declared:
db = web.database(dbn='mysql',\
                  user='user',\
                  pw='password',\
                  db='todo',\
                  host='mysql.example.com')
Also, the PostgreSQL example translates into MySQL like this:
CREATE TABLE todo (   id serial primary key,   title text,   
                    created timestamp default now(),   
        `done` boolean default '0'    );
specifically boolean is an synonym for tinyint in MySQL so it uses not 'f' but '0' to represent false.

The output code from my tutorial is:

code.py:

#!/usr/bin/env python
# Filename:                code.py
# Description:             intro to web.py
# Supported Langauge(s):   Python 2.7.x
# Time-stamp:              <2011-06-04 18:15:06 someguy> 
# -------------------------------------------------------
import web
# -------------------------------------------------------
render = web.template.render('templates/')
urls = (
    '/', 'index',
    '/add', 'add'
)
app = web.application(urls, globals())
db = web.database(dbn='mysql',\
                  user='todo',\
                  pw='redacted',\
                  db='todo',\
                  host='mysql.example.com')
# -------------------------------------------------------
class index:        
    def GET(self):
        todos = db.select('todo')
        return render.index(todos)

class add:
    def POST(self):
        i = web.input()
        n = db.insert('todo', title=i.title)
        raise web.seeother('/')
# -------------------------------------------------------
if __name__ == "__main__":
    app.run()
templates/index.html
$def with (todos)
<ul>
$for todo in todos:
    <li id="t$todo.id">$todo.title</li>
</ul>

<form method="post" action="add">
<p><input type="text" name="title" /> 
<input type="submit" value="Add" /></p>
</form>