first, we need to download, and install web.py which is easy, just download the file, extract it and type
python setup.py installbefore beginning, make sure web.py is installed correctly, by;
$ python >>> import web
you should not see any importerror message.
in a web.py document, websites urls are written in
urls list, and map them to the correspond classes. here's a simple hello world application in web.py
import web
urls = (
'/', 'index',
)
class index(object):
def GET(self):
return 'hello world'
app = web.application(urls, globals())
if __name__ == '__main__':
app.run()
ok, i think you get the structure of a web.py document. we can continue on building our little website. let's start with the basic library imports.
as i said above, my preference of template engine is mako, so we need to make some configuration.
import web
from web.contrib.template import render_mako
render = render_mako(
directories = ['templates'],
module_directory = ['modules'],
input_encoding = 'utf-8',
output_encoding = 'utf-8',
default_filters = ['decode.utf8'],
)
and urls of our website;
urls = (
'^/(.*)/', 'redirect',
'/posts/(\d-)', 'posts',
'/', 'index',
)
you may wonder the purpose of '^/(.*)/', 'redirect'. that's my preference again. when a user tries to go http://example/posts/34535/ address, he will be redirected to http://example/posts/34535.let's continue with index class.
class index(object):
def GET(self):
web.header('Content-type', 'text/html; charset=utf-8')
posts = db.get_posts()
if not posts:
raise web.notfound()
return render.index(posts = posts)
first, we define some header, like content-type of the document, which is html. secondly; we get some posts from database which we have not defined yet. don't worry about it for now, and thirdly, we render index.html file.and our posts class, which accepts commenting from users.
class posts(object):
def GET(self, entry_id):
web.header('Content-type', 'text/html; charset=utf-8')
if not entry_id:
raise web.notfound()
post = db.get_posts(entry_id)
if not post:
raise web.notfound()
form = comment_form()
return render.post(post = post, form = form)
like db.get_posts, we have not yet defined comment_form. db.py file is the file that we handle database processes.
our db.py file as follows;
import web
USER = 'db_username'
PASS = 'db_passwd'
DB = 'db_test'
conn = web.database(db='mysql', user = USER, pw = PASS, charset='utf-8')
def get_posts():
res = conn.select('db_table',
what = 'id, title, entry',
order = 'created DESC',
limit = 30
)
return res
def get_post(post_id):
res = conn.select('db_table',
what = 'id, title, entry',
where = 'id = $id',
limit = 1,
vars = {'id' = post_id}
)
if not res:
return None
return res[0]
in what we write the columns we want to retrieve, where is the filter options. when you retrieve the page you can see the query that is executed in the console.
web.py also comes with handy forms class, which you can create forms automatically, and validation is very ease with the help of the
lambda.our forms.py class as follows;
from web import form
class MyForm(form.Form):
def render(self):
out = ''
out += self.rendernote(self.note)
out += '\n'
for i in self.inputs:
out += '<p><label for="%s">%s<span id="note_%s">%s</span></label>' % (i.id, i. description, i.id, self.rendernote(i.note))
out += i.pre + i,render() + i.post + '</p>'
return out
def rendernote(self, note):
if note:
err = '%s' % (note)
return err
else: return ''
comment_form = MyForm(
form.Textbox('username',
form.Validator('please type your name', lambda x : 255 > len(unicode(x)) > 2),
description = 'your name:',
id = 'id_names',
class _= 'css_class',
),
form.Textarea('message',
form.Validator('please write your message', lambda x : len(unicode(x)) > 10),
description = 'your message',
rows = 10,
cols = 50,
class _= 'css_class',
),
)
we defined our own form class which is MyForm, because web.py's default form render class uses tables which is not a valid tag in xhtml strict. comment_form is our comment form renderer.since we have to
POST comment form, we need to edit posts class as follows;
class posts(object):
def GET(self, entry_id):
web.header('Content-type', 'text/html; charset=utf-8')
if not entry_id:
raise web.notfound()
post = db.get_posts(entry_id)
if not post:
raise web.notfound()
form = comment_form()
return render.post(post = post, form = form)
def POST(self, entry_id):
web.header('Content-type', 'text/html; charset=utf-8')
if not entry_id:
raise web.notfound()
post = db.get_posts(entry_id)
if not post:
raise web.notfound()
form = comment_form()
if form.validates():
res = db.set_comment(form)
if res:
raise web.seeother('/index?done=true')
return render.post(post = post, form = form)
it's pretty ease. we have finished our simple site with commenting enabled options. and now we can continue to templates. first, we'll create a base.html file, and our index.html, and post.html files will inherit our base.html file.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>My Site</title>
<meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<link rel="stylesheet" type="text/css" media="screen,projection" href="/static/css/style.css" />
</head>
<body>
<h1>Welcome to my site!</h1>
${self.content()}
</body>
</html>
this is our base.html file. in index.html we'll define a new def which will be named content.here's our
index.html file;
<%inherit file="base.html" />
<%def name="content()">
<ul>
%for post in posts:
<li>${post.title}</li>
%endfor
</ul>
</%def>
and
post.html file as follows;
<%inherit file="base.html" />
<%def name="content()">
<div>
<h1>${post.title}</h1>
<p>${post.entry}</p>
%endfor
</div>
<div>
<form action="/posts/${post.id}" method="post">
${form.render()}
</form>
</div>
</%def>
i didn't cover the topics like login, and some more advanced stuff, but if you get the idea of this simple web application you'll notice doing such thing is very ease in web.py. my python web framework choice is web.py, 'cos of its simplicity, and let's you code in python.