Skip to content
This repository
Newer
Older
100644 264 lines (161 sloc) 11.79 kb
513f3fd1 » aaronsw
2012-08-06 remove BOM
1 ---
92aad4b3 » five3
2012-08-06 add language link tutorial3 file
2 layout: default
3 title: Tutorial
4 ---
5
6 # Tutorial
7
66340277 » nopri
2013-03-06 add tutorial.id.md (Bahasa Indonesia)
8 Other languages : [chinese 简体中文 ](/docs/0.3/tutorial.zh-cn) | [français](/docs/0.3/tutorial.fr) | [Bahasa Indonesia](/docs/0.3/tutorial.id) | ...
92aad4b3 » five3
2012-08-06 add language link tutorial3 file
9
10 ## Summary
11
12 * [Starting](#starting)
13 * [URL Handling](#urlhandling)
14 * [GET and POST: the difference](#getpost)
15 * [Start the server](#start)
16 * [Templating](#templating)
17 * [Forms](#forms)
18 * [Databasing](#databasing)
19 * [Developing](#developing)
20 * [What next?](#whatnext)
21
22 ## Starting
23
24 So you know Python and want to make a website. web.py provides the code to make that easy.
25
26 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 <a href="/install">install</a> for details.)
27
28 Let's get started.
29
30 <a name="urlhandling"> </a>
31 ## URL Handling
32
33 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](http://del.icio.us/), the URLs are even part of the user interface. web.py makes it easy to make great URLs.
34
35 To get started with your web.py application, open up a new text file (let's call it `code.py`) and type:
36
37 import web
38
39 This imports the web.py module.
40
41 Now we need to tell web.py our URL structure. Let's start out with something simple:
42
43 urls = (
44 '/', 'index'
45 )
46
47 The first part is a [regular expressions](http://osteele.com/tools/rework/) that matches a URL, like `/`, `/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.
48
49 This line says we want the URL `/` (i.e. the front page) to be handled by the class named `index`.
50
51 <a name="getpost"> </a>
52 ## GET and POST: the difference
53
54 Now we need to write the `index` 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`).
55
56 `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!).
57
58 In our web.py code, we make the distinction between the two clear:
59
60 class index:
61 def GET(self):
62 return "Hello, world!"
63
64 This `GET` function will now get called by web.py anytime someone makes a `GET` request for `/`.
65
66 Now we need to create an application specifying the urls and a way to tell web.py to start serving web pages:
67
68 if __name__ == "__main__":
69 app = web.application(urls, globals())
70 app.run()
71
72 First we tell web.py to create an application with the URLs we listed above, looking up the classes in the global namespace of this file.
73 And finally we make sure that web.py serves the application we created above.
74
75 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.
76
77 For easier access, here's how your code should look like:
78
79 import web
80
81 urls = (
82 '/', 'index'
83 )
84
85 class index:
86 def GET(self):
87 return "Hello, world!"
88
89 if __name__ == "__main__":
90 app = web.application(urls, globals())
91 app.run()
92
93 <a name="start"> </a>
94 ## Start the server
95
96 If you go to your command line and type:
97
98 $ python code.py
99 http://0.0.0.0:8080/
100
101 You now have your web.py application running a real web server on your computer. Visit that URL and you should see "Hello, world!" (You can add an IP address/port after the "code.py" bit to control where web.py launches the server. You can also tell it to run a `fastcgi` or `scgi` server.)
102
103 **Note:** You can specify the port number to use on the command line like this
104 if you can't or don't want to use the default:
105
106 $ python code.py 1234
107
108
109 <a name="templating"> </a>
110 ## Templating
111
112 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.
113
114 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:
115
116 <em>Hello</em>, world!
117
118 Or you can use web.py's templating language to add code to your HTML:
119
120 $def with (name)
121
122 $if name:
123 I just wanted to say <em>hello</em> to $name.
124 $else:
125 <em>Hello</em>, world!
126
127 As you can see, the templates look a lot like Python files except for the `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`.
128
129 Now go back to `code.py`. Under the first line, add:
130
131 render = web.template.render('templates/')
132
133 This tells web.py to look for templates in your templates directory. Then change `index.GET` to:
134
135 name = 'Bob'
136 return render.index(name)
137
138 ('index' is the name of the template and 'name' is the argument passed to it)
139
140 Visit your site and it should say hello to Bob.
141
142 But let's say we want to let people enter their own name in. Replace the two lines we added above with:
143
144 i = web.input(name=None)
145 return render.index(i.name)
146
147 Visit `/` and it should say hello to the world. Visit `/?name=Joe` and it should say hello to Joe.
148
149 Of course, having that `?` in the URL is kind of ugly. Instead, change your URL line at the top to:
150
151 '/(.*)', 'index'
152
153 and change the definition of `index.GET` to:
154
155 def GET(self, name):
156 return render.index(name)
157
158 and delete the line setting name. Now visit `/Joe` and it should say hello to Joe.
159
66340277 » nopri
2013-03-06 add tutorial.id.md (Bahasa Indonesia)
160 If you wish to learn more about web.py templates, visit the <a href="/docs/0.3/templetor">templetor page</a>.
92aad4b3 » five3
2012-08-06 add language link tutorial3 file
161
162 <a name="forms"> </a>
163 ## Forms
164
165 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.
166 If you want to learn more about using the module forms web.py, see the [Documentation](/docs/0.3) or direct link to [Form Library](/form)
167
168 <a name="databasing"> </a>
169 ## Databasing
170
171 **Note:** Before you can start using a database, make sure you have the appropriate database library installed. For MySQL databases, use [MySQLdb](http://sourceforge.net/project/showfiles.php?group_id=22307) and for Postgres use [psycopg2](http://initd.org/pub/software/psycopg/).
172
173 First you need to create a database object.
174
175 db = web.database(dbn='postgres', user='username', pw='password', db='dbname')
176
177 (Adjust these -- especially `username`, `password`, and `dbname` -- for your setup. MySQL users will also want to change `dbn` definition to `mysql`.)
178
179 That's all you need to do -- web.py will automatically handle connecting and disconnecting from the database.
180
181 Using your database engines admin interface, create a simple table in your database:
182
183 CREATE TABLE todo (
184 id serial primary key,
185 title text,
186 created timestamp default now(),
187 done boolean default 'f' );
188
189 And an initial row:
190
191 INSERT INTO todo (title) VALUES ('Learn web.py');
192
193 Return to editing `code.py` and change `index.GET` to the following, replacing the entire function:
194
195 def GET(self):
196 todos = db.select('todo')
197 return render.index(todos)
198
199 and change back the URL handler to take just `/` as in:
200
201 '/', 'index',
202
203 Edit and replace the entire contents of `index.html` so that it reads:
204
205 $def with (todos)
206 <ul>
207 $for todo in todos:
208 <li id="t$todo.id">$todo.title</li>
209 </ul>
210
211 Visit your site again and you should see your one todo item: "Learn web.py". Congratulations! You've made a full application that reads from the database. Now let's let it write to the database as well.
212
213 At the end of `index.html`, add:
214
215 <form method="post" action="add">
216 <p><input type="text" name="title" /> <input type="submit" value="Add" /></p>
217 </form>
218
219 And change your URLs list to read:
220
221 '/', 'index',
222 '/add', 'add'
223
224 (You've got to be very careful about those commas. If you omit them, Python adds the strings together and sees `'/index/addadd'` instead of your list of URLs!)
225
226 Now add another class:
227
228 class add:
229 def POST(self):
230 i = web.input()
231 n = db.insert('todo', title=i.title)
232 raise web.seeother('/')
233
234 (Notice how we're using `POST` for this?)
235
236 `web.input` gives you access to any variables the user submitted through a form.
237
238 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:
239
240 post_data=web.input(name=[])
241
242 `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.
243
244 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.
245
246 `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.
247
248 You can find the full details on these and all the web.py functions in [the documentation](/docs/0.3).
249
250 <a name="developing"> </a>
251 ## Developing
252
253 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.
254
255 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.
256
257 web.config.debug = False
258
259 <a name="whatnext"> </a>
260 ## What Next ?
261
262 This ends the tutorial for now. Take a look at the [cookbook](/cookbook/) and the [code examples](/src/) for lots more cool stuff you can do with web.py.
263 Also don't forget about the [api reference](/docs/0.3/api)
264
Something went wrong with that request. Please try again.