Translations: 日本語 Русский Español Português: 1 2 3
Install
If you want to do the whole tutorial, you'll need to have installed web.py, flup, Cheetah, psycopg2, and Postgres. For details, see the front page.
URL Handing
Open up a new file in your favorite text editor. Maybe call it code.py
. Type the code in:
import web
This imports the web.py framework.
urls = (
'/', 'view'
)
This is your list of url to function mapping. The first part is a regular expression that matches a path, like /
, /help/faq
, /item/(\d+)
, etc. (The \d+
matches a sequence of digits. The parentheses say to capture that piece of the match for later on.) The second part is the name of a class to send the request to, like view
, welcomes.hello
(which gets the hello
class of the welcomes
module), or get_\1
. \1
is replaced by the first capture of your regular expression; any remaining captures get passed to your function.
class view:
def GET(self):
Here's the class hello with its function GET. As you might have guessed, GET is called when somebody calls the HTTP GET method on your URL (i.e. they visit your URL).
print "Hello, world!"
This returns the plain text 'Hello, world!' to the visitor.
web.internalerror = web.debugerror
This line tells web.py to display a page with lots of helpful debugging information whenever it reaches an error. You'll want to comment out this line when launch the site so users don't see it.
if __name__ == '__main__': web.run(urls, web.reloader)
This tells web.py to run your app when the file is executed. The first argument, urls
, is the url-to-function mapping defined above. The other arguments are for "middleware" -- wrapper functions that help with some part of your application. Here we're using the reloader, which reloads source code automatically when it changes, so we don't have to reboot the server every time. You probably want to take this out when you make your site public, but it's invaluable while developing. There's also web.profiler
, which outputs information about how much time each function takes to the end of web pages, so that you can make your code faster.
Run python code.py
to start a web server running your app. (To run it on port 8002, run python code.py 8002
) You can also run code.py as a CGI script or a FastCGI script -- it will automatically do the right thing. (And since web.py
is built on WSGI, the Python web app interface standard, you can run it in all sorts of other things, including mod_python, if you want.)
Now if you visit your site in a web browser, you should see it say 'Hello, world!'.
Templating
Make a new directory named templates
. Inside, open up a new file whose name ends with .html
. Maybe call it view.html
.
#if $name
I just wanted to say hello to $name.
#else
Hello, world!
#end if
Now go back to code.py
. Change view.GET so it reads:
name = 'Bob'
web.render('view.html')
Now if you visit your site in a web browser, you should see it say hello to Bob.
These templates are Cheetah Templates. All of the important features are covered in a one page tutorial -- mostly, they work just like Python code embedded into HTML (or whatever format you're writing).
Warning: The current plan is for Cheetah to be replaced with something mostly the same but a little simpler and more powerful. This format has been designed but the implementation is unfinished.
Custom URLs
Change your urls list so that it reads:
'/(.*)', 'view'
Now change the definition of view.GET so that it reads:
def GET(self, name):
and get rid of the line setting name.
Now if you visit /Joe
you should see it say hello to Joe. If you visit /
, it should say 'Hello, world!'.
Databasing
Above the web.run
line, add:
web.db_parameters = dict(dbn='postgres', user='me', pw='pass', db='dbname')
changing the values to reflect your database setup. (For example, MySQL users will want to change dbn to be mysql
.)
Create a simple table in your database:
CREATE TABLE todo (
id serial primary key,
title text,
created timestamp default now(),
done boolean default 'f'
);
And a sample row:
INSERT INTO todo (title) VALUES ('Learn web.py');
Back in code.py
, add this line to the top of view.GET:
todos = web.select("todo")
Edit view.html
so that it reads:
<ul>
#for todo in $todos
<li id="t$todo.id">$todo.title</li>
#end for
</ul>
Visiting your website should now show your one todo item: 'Learn web.py'.
Add to the end of view.html
:
<form method="post" action="add">
<p><input type="text" name="title" /> <input type="submit" value="Add" /></p>
</form>
Change your urls list so that it reads:
'/', 'view',
'/add', 'add'
Change view.GET
so it no longer takes any additional parameters:
def GET(self):
And underneath the view
class add:
class add:
def POST(self):
i = web.input()
n = web.insert('todo', title=i.title)
web.seeother('./#t'+str(n))
web.insert
returns the id of the new item inserted and then web.seeother
is used to redirect the user to it.
Quickly: web.transact()
starts a transaction. web.commit()
commits it; web.rollback()
rolls it back. web.update
works just like web.insert
except instead of returning the id it takes it (or a string WHERE clause) after the table name.
Now you can add todo items to your list.
Aside: The Storage Object
Both web.input
and web.query
, along with many other things in web.py, return "Storage objects". A Storage object is just like a dictionary, except that d.foo is the same as d['foo']. This cuts down a lot on typing.
Cookies
Cookies work pretty much the same way as web.input
. web.cookies()
returns a Storage object with all set cookies. web.setcookie(name, value, expires="")
sets cookies.
Both web.input
and web.cookies
take a series of arguments and keyword arguments. If you call web.input('color', times=1)
, for example, it will throw an error if it does not receive a query argument named color
and if it does not receive one named times
it will set it to 1.
A common idiom is:
try: i = web.input('foo', bar=2)
except KeyError: return web.badrequest()
This ends the tutorial for now. Next up: forms.
Want more? Check out the full docs.
Comments? Questions? Suggestions? Requests? Email webpy@aaronsw.com.