Summary
- Starting
- URL Handling
- GET and POST: the difference
- Start the server
- Templating
- Forms
- Databasing
- Developing
- What next?
Starting
subscribe to our channel
So you know Python and want to make a website. web.py provides the code to make that easy.
If you want to do the whole tutorial, you’ll need to have installed Python, web.py, flup, psycopg2, and Postgres (or equivalent database and Python driver). (See install for details.)
Let’s get started.
URL Handling
The most important part of any website is its URL structure. Your URLs aren’t just the thing that your visitors see and email to their friends, they also provide a mental model of how your website works. On popular sites like del.icio.us, the URLs are even part of the user interface. web.py makes it easy to make great URLs.To get started with your web.py application, open up a new text file (let’s call it
code.py
) and type:import web
Now we need to tell web.py our URL structure. Let’s start out with something simple:
urls = (
'/', 'index'
)
/
, /help/faq
, /item/(\d+)
, etc. (i.e. \d+
would match a sequence of digits). The parentheses say to capture that
piece of the matched data for use later on. The second part is the name
of a class to send the request to, like index
, 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.This line says we want the URL
/
(i.e. the front page) to be handled by the class named index
.GET and POST: the difference
Now we need to write theindex
class. While most people don’t notice it just browsing around, your
browser uses a language known as HTTP for communicating with the World
Wide Web. The details aren’t important, but the basic idea is that Web
visitors ask web servers to perform certain functions (like GET
or POST
) on URLs (like /
or /foo?f=1
).GET
is the one we’re all familiar with, the one used to request the text of a web page. When you type harvard.edu
into your web browser, it literally asks the Harvard web server to GET /
. The second-most famous, POST
, is often used when submitting certain kinds of forms, like a request to purchase something. You use POST
whenever the act of submitting a request does something (like charge your credit card and process an order). This is key, because GET
URLs can be passed around and indexed by search engines, which you definitely want for most of your pages but definitely don’t want for things like processing orders (imagine if Google tried to buy everything on your site!).In our web.py code, we make the distinction between the two clear:
class index:
def GET(self):
return "Hello, world!"
GET
function will now get called by web.py anytime someone makes a GET
request for /
.Now we need to create an application specifying the urls and a way to tell web.py to start serving web pages:
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
Now notice that although I’ve been talking a lot here, we only really have five or so lines of code. That’s all you need to make a complete web.py application.
For easier access, here’s how your code should look like:
import web
urls = (
'/', 'index'
)
class index:
def GET(self):
return "Hello, world!"
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
Start the server
subscribe to our channel
If you go to your command line and type:
$ python code.py
http://0.0.0.0:8080/
fastcgi
or scgi
server.)Note: You can specify the port number to use on the command line like this if you can’t or don’t want to use the default:
$ python code.py 1234
Templating
Writing HTML from inside Python can get cumbersome; it’s much more fun to write Python from inside HTML. Luckily, web.py makes that pretty easy.Let’s make a new directory for our templates (we’ll call it
templates
). Inside, make a new file whose name ends with HTML (we’ll call it index.html
). Now, inside, you can just write normal HTML:<em>Hello</em>, world!
$def with (name)
$if name:
I just wanted to say <em>hello</em> to $name. with the help
of <a href="https://thepythoncoding.blogspot.com/">The Python Coding</a>
$else:
<em>Hello</em>, world!
def with
statement at the top (saying what the template gets called with) and the $
s placed in front of any code. Currently, template.py requires the $def
statement to be the first line of the file. Also, note that web.py
automatically escapes any variables used here, so that if for some
reason name
is set to a value
containing some HTML, it will get properly escaped and appear as plain
text. If you want to turn this off, write $:name
instead of $name
.Now go back to
code.py
. Under the first line, add:render = web.template.render('templates/')
index.GET
to:name = 'Bob'
return render.index(name)
Visit your site and it should say hello to Bob.
But let’s say we want to let people enter their own name in. Replace the two lines we added above with:
i = web.input(name=None)
return render.index(i.name)
/
and it should say hello to the world. Visit /?name=Joe
and it should say hello to Joe.Of course, having that
?
in the URL is kind of ugly. Instead, change your URL line at the top to:'/(.*)', 'index'
index.GET
to:def GET(self, name):
return render.index(name)
/Joe
and it should say hello to Joe.If you wish to learn more about web.py templates, visit the templetor page.
Forms
subscribe to our channel
The form module of web.py allows the ability to generate html forms, get user input, and validate it before processing it or adding it to a database. If you want to learn more about using the module forms web.py, see the Documentation or direct link to Form Library
Databasing
Note: Before you can start using a database, make sure you have the appropriate database library installed. For MySQL databases, use MySQLdb and for Postgres use psycopg2.First you need to create a database object.
db = web.database(dbn='postgres', user='username', pw='password', db='dbname')
username
, password
, and dbname
– for your setup. MySQL users will also want to change dbn
definition to mysql
.)That’s all you need to do – web.py will automatically handle connecting and disconnecting from the database.
Using your database engines admin interface, create a simple table in your database:
CREATE TABLE todo (
id serial primary key,
title text,
created timestamp default now(),
done boolean default 'f' );
INSERT INTO todo (title) VALUES ('Learn web.py');
code.py
and change index.GET
to the following, replacing the entire function:def GET(self):
todos = db.select('todo')
return render.index(todos)
/
as in:'/', 'index',
index.html
so that it reads:$def with (todos)
<ul>
$for todo in todos:
<li id="t$todo.id">$todo.title</li>
</ul>
At the end of
index.html
, add:<form method="post" action="add">
<p><input type="text" name="title" /> <input type="submit" value="Add" /></p>
</form>
'/', 'index',
'/add', 'add'
'/index/addadd'
instead of your list of URLs!)Now add another class:
class add:
def POST(self):
i = web.input()
n = db.insert('todo', title=i.title)
raise web.seeother('/')
POST
for this?)web.input
gives you access to any variables the user submitted through a form.Note: In order to access data from multiple identically-named items, in a list format (e.g.: a series of check-boxes all with the attribute name=”name”) use:
post_data=web.input(name=[])
db.insert
inserts values into the database table todo
and gives you back the ID of the new row. seeother
redirects users to that URL.Some quick additional notes:
db.update
works just like db.insert
except instead of returning the ID it takes it (or a string WHERE
clause) after the table name.web.input
, db.query
, and other functions in web.py return “Storage objects”, which are just like dictionaries except you can do d.foo
in addition to d['foo']
. This really cleans up some code.You can find the full details on these and all the web.py functions in the documentation.
Developing
web.py also has a few tools to help us with debugging. When running with the built-in webserver, it starts the application in debug mode. In debug mode any changes to code and templates are automatically reloaded and error messages will have more helpful information.The debug is not enabled when the application is run in a real webserver. If you want to disable the debug mode, you can do so by adding the following line before creating your application/templates.
web.config.debug = False