--- layout: default title: web.py 0.2 tutorial --- # web.py 0.2 tutorial ## Startujemy A wiÄc potrafisz programowaÄ w Pythonie i pragniesz zrobiÄ swojÄ stronÄ. Z web.py to zadanie staje siÄ wyjÄ tkowo Åatwe. Jeżeli masz zamiar przejÅÄ przez caÅy tutorial, bÄdziesz potrzebowaÅ mieÄ zainstalowane: Python, web.py, flup, psycopg2 i Postgress (lub innÄ bazÄ danych oraz pythonowy driver do niej). Po szczegóÅy zerknij na [webpy.org](http:webpy.org/). Jeżeli masz już istniejÄ cy projekt stworzony z użyciem web.py, zajrzyj na stronÄ opisujÄ cÄ [upgrade](http://webpy.infogami.com/upgrade_to_point2). Znajdziesz tam informacje przydatne podczas migracji. A wiÄc zaczynamy. ## ObsÅuga URL Jednym z ważniejszych aspektów w projekcie serwisu webowego jest jego struktura odnoÅników (urli). SÄ one nie tylko tym, co osoby odwiedzajÄ cy stronÄ widzÄ i ewentualnie przekazujÄ swoim znajomym, ale także dajÄ wyobrażenie o tym, jak twój serwis dziaÅa. Niektóre popularne serwisy jak [del.icio.us](http://del.icio.us/) uczyniÅy odnoÅniki czÄÅciÄ interfejsu użytkownika. web.py umożliwia stworzenie Åwietnych odnoÅników w prosty sposób. Å»eby zaczÄ Ä przygodÄ z web.py, otwórz nowy plik tekstowy (nazwijmy go code.py) i napisz w nim: import web Instrukcja ta spowoduje zaimportowanie moduÅu web.py. Teraz trzeba wskazaÄ strukturÄ odnoÅników, jakÄ ma obsÅugiwaÄ web.py. Zacznijmy od czegoÅ naprawdÄ prostego: urls = ( '/', 'index', '', 'index' ) Pierwsza czÄÅÄ każdego wpisu to [wyrażenie regularne](http://osteele.com/tools/rework/) do którego bÄdzie porównywany odnoÅnik, np. `/`, `/help/faq`, `/item/(\d+)`, itp. (`\d+` zostanie dopasowane do sekwencji cyfr, czyli liczby). Nawiasy powodujÄ "zÅapanie" czÄÅci odnoÅnika z celu dalszego użycia. Druga czÄÅÄ wpisu to nazwa pythonowej klasy, która ma obsÅużyÄ zapytanie dla danego odnoÅnika, np. `index`, `view`, `welcomes.hello` (czyli klasa hello w module welcomes) lub `get_\1`. `\1` zostanie zastÄ pione przez pierwsze dopasowanie wyrażenia regularnego, reszta dopasowaÅ zostanie przekazana jako parametry do klasy. Powyższy kod oznacza, że chcemy aby odnoÅnik `/` (to jest strona powitalna) byÅa obsÅugiwana przez klasÄ nazwanÄ `index`. Teraz trzeba owÄ klasÄ napisaÄ. Prawdopodobie wiÄkszoÅÄ osób nawet nie zauważa tego, że przeglÄ darka używa protokoÅu zwanego HTTP do komunikacji z sieciÄ WWW. Nie sÄ tutaj istotne szczegóÅy, ale podstawowa idea jest taka, że serwery WWW sÄ proszone o wykonanie pewnych funkcji (jak `GET` lub `POST`) przy użyciu odnoÅników (jak `/` lub `/foo?f=1`). Funkcja `GET` jest tÄ najbardziej popularnÄ i najczÄÅciej używanÄ do pobrania z serwera strony web. WpisujÄ c w przeglÄ darce adres `harvard.edu` w istocie przeglÄ darka poprosi serwer Harvardu o wykonanie funkcji `GET /`. DrugÄ najpopularniejszÄ funkcjÄ jest `POST`. NajczÄÅciej używana jest do wysyÅania rozmaitych formularzy, np. z proÅba o kupienie czegoÅ. W naszym kodzie rozróżnienie tych dwóch funkcji jest bardzo proste i czytelne: class index: def GET(self): print "Hello, world!" Zdefiniowana funkcja `GET` bÄdzie wywoÅana przez web.py za każdym razem gdy serwer dostanie proÅbÄ o odnoÅnik `/`. Dobrze, teraz jeszcze musimy dopisaÄ ostatniÄ linijkÄ uruchamiajÄ cÄ web.py: if __name__ == "__main__": web.run(urls, globals()) Kod ten mówi web.py żeby dostarczaÅ odnoÅniki wymienione powyżej, używajÄ c do tego klass zdefiniowanych w gÅównej przestrzeni nazw tego pliku. Warto zauważyÄ, że pomimo dÅugiego opisu, tak naprawdÄ napisaliÅmy mniej wiÄcej 5 linii kodu. Tylko tyle potrzeba, aby stworzyÄ kompletnÄ aplikacjÄ web.py. Można jÄ teraz uruchomiÄ w ten sposób: $ python code.py Launching server: http://0.0.0.0:8080/ WÅaÅnie uruchomiÅeÅ swojÄ wÅasnÄ aplikacjÄ web.py i serwer www na swoim komputerze. Wpisz w przeglÄ darkÄ ten adres aby zobaczyÄ "Hello, world!" (możesz dopisaÄ po code.py adress ip/port, możesz też poleciÄ uruchomienie serwera `fastcgi` lub `scgi`). **Uwaga:** Możesz podaÄ numer portu na którym ma dziaÅaÄ serwer jeżeli nie chcesz lub nie możesz użyÄ tego domyÅlnego: $ python code.py 1234 ## Rozwijanie aplikacji web.py posiada kilka narzÄdzi pomocnych w tropieniu i usuwaniu ewentualnych bÅÄdów. Przed `if __name__` w ostatniej linijce dopisz: web.webapi.internalerror = web.debugerror Spowoduje to wyÅwietlanie bardziej przyjaznych komunikatów o bÅÄdach. Dodatkowo w ostatniej linijce dopisz `web.reloader`: if __name__ == "__main__": web.run(urls, globals(), web.reloader) Spowoduje to użycie middleware'u web.reloader, który bÄdzie przeÅadowywaÅ twoje pliki z kodem za każdym razem gdy coÅ w nich zmienisz, tak abyÅ widziaÅ te zmiany od razu w dziaÅajÄ cym serwerze. Chociaż mimo wszystko, poważniejsze zmiany w kodzie i tak bÄdÄ wymagaÅy restartu serwera. Prawdopodobnie bÄdziesz chciaÅ wyÅÄ czyÄ tÄ opcjÄ w docelowej wersji serwisu, ale jest to spore uÅatwienie na czas kodowania. DostÄpny jest także `web.profiler`, który dostarcza informacje o tym jak szybko (lub wolno) sÄ wykonywane twoje funkcje. ## Szablony Pisanie kodu HTML bezpoÅrednio w Pytonie jest niezbyt wygodne. Zdecydowanie ciekawsze jest pisanie kodu Pythona wewnÄ trz HTML. Na szczÄÅcie web.py czyni to caÅkiem Åatwym. **Uwaga:** Stare wersje web.py używaÅy [Cheetah](http://www.cheetahtemplate.org/). Możesz oczywiÅcie nadal używaÄ tych lub innych szablonów, ale Cheetah nie sÄ już oficjalnie wspierane. (translation is in progress...) 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: Hello, world! Or you can use web.py's templating language to add code to your HTML: $def with (name) $if name: I just wanted to say hello to $name. $else: Hello, world! **Note: Currently, four spaces are required for indentation.** 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`. Now go back to `code.py`. Under the first line, add: render = web.template.render('templates/') This tells web.py to look for templates in your templates directory. Then change `index.GET` to: name = 'Bob' print render.index(name) ('index' is the name of the template and 'name' is the argument passed to it) Visit your site and it should say hello to Bob. **Development tip:** Add , `cache=False` to the end of your `render` call to have web.py reload your templates every time you visit the page. 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) print render.index(i.name) Visit `/` 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' and change the definition of `index.GET` to: def GET(self, name): print render.index(name) and delete the line setting name. Now visit `/Joe` and it should say hello to Joe. If you wish to learn more about web.py templates, vist the [templetor page](/templetor). ## Databasing **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/). Above your `web.run` line add: web.config.db_parameters = dict(dbn='postgres', user='username', pw='password', db='dbname') (Adjust these -- especially `username`, `password`, and `dbname` -- for your setup. MySQL users will also want to change `dbn` definition to `mysql`.) If you're running a web application, that's all you need to do -- web.py will automatically handle connecting and disconnecting from the database. But if you're working from the command line or starting your own thread, you need to call `web.load()` to connect and `web.unload()` to disconnect. 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' ); And an initial row: INSERT INTO todo (title) VALUES ('Learn web.py'); Return to editing `code.py` and change `index.GET` to the following, replacing the entire function: def GET(self): todos = web.select('todo') print render.index(todos) and change back the URL handler to take just `/` as in: '/', 'index', Edit and replace the entire contents of `index.html` so that it reads: $def with (todos)