CGI-ohjelmointi, HTTP-protokolla
- Lomake - form
- Lomake-elementit
- Kentän otsikko - label
- input-elementti
- Tekstialue - textarea
- Valintalista - select
- Lomake-elementtien ryhmittely - fieldset
- Elementtien ryhmän otsikko - legend
- Lomakkeen käsittely
- HTTP (HyperText Transfer Protocol)
- Pythonin cgi-kirjasto
- CGI-ohjelmointi Pythonilla
- Templatet ja Jinja
- Python, merkistöt ja erikoismerkit webissä
Jatketaan Pythonin, CGI-ohjelmoinnin ja HTTP-protokollan parissa.
Uusin Python ja CGI-ohjelmointiluento (youtube)
Vanha Python ja CGI-ohjelmointiluento (youtube)
Luentoesimerkit: jinja.cgi-esimerkki (Lähdekoodi, Jinja template)
Toinen jinja-esimerkki (Lähdekoodi, Pohjatemplate, Toinen template)
JSON, omat luokat, lomakkeen korvaaminen linkillä (Lähdekoodi, Template )
Lomake - form
form-elementti määrittelee lomakkeen varsinaisen alkamis- ja loppumiskohdan. form-elementin sisään sijoitetaan kaikki varsinaiset lomake-elementit (tekstikentät, valintaruudut, yms.), jotka tulevat näkyviin lomakkeelle. form-elementin attribuuteilla eli ominaisuuksilla voidaan määritellä tarkemmin lomakkeen käyttäytymistä. Seuraavassa lyhyt esimerkki form-elementin käytöstä:
<!DOCTYPE html> <html> <head> <title>Esimerkkilomake</title> </head> <body> <h1>Esimerkkilomake</h1> <form action="http://palvelin/teepase.cgi" method="post"> .. lomake-elementit tulevat tänne.. </form> </body> </html>
action-attribuutti
action-attribuutti kertoo lomakkeelle osoitteen, jossa lomakkeen käsittelevä CGI-ohjelma sijaitsee. Seuraavassa muutama esimerkki action-attribuutin käytöstä. Ensimmäisessä esimerkissä on perinteinen absoluuttinen hakemistoviittaus ohjelmaan, joka käsittelee lomakkeelle syötetyn datan.
<form action="http://palvelin/teepase.cgi" method="post">
Edellisen esimerkin mukaisesti lähetettynä data tulee koodattuna application/x-www-form-urlencoded-muodossa.
<form action="http://palvelin/teepase.cgi" method="post" enctype="multipart/form-data">
Antamalla enctype-attribuutin arvoksi multipart/form-data voidaan lomakkeeseen lisätä myös tiedostoja
method-attribuutti
method-attribuutti kertoo kuinka lomakkeen sisältämä data toimitetaan datan käsittelevälle ohjelmalle. Attribuutin mahdolliset arvot ovat post ja get.
method-attribuutti arvolla get saa aikaan lomakkeella olevien tietojen siirtämisen URL:n yhteydessä. Seuraavassa on esitelty muoto, jossa tiedot siirretään lomakkeen käsittelevälle ohjelmalle. Lomakkeelta siirrettävät tiedot ovat nähtävillä selaimen osoitepalkissa (location, address)
http://palvelin/teepase.cgi?Nimi=Etunimi+Sukunimi&email=Sahk%F6postiosoite&kommentti=t%E4h%E4n+kommentti&laheta=L%E4het%E4+kommenttisi
URL:n mukana tulevien tietojen muoto näyttää ensi silmäyksellä sekavalle. Kuitenkin sieltä on helposti erotettavissa lomakkeen tiedot. Lomakkeen käsittelevän ohjelman osoite ja lomakkeen tiedot on erotettu kysymysmerkillä (?). Eri kenttien tiedot on erotettu &-merkillä. Lomakekentän nimi ja arvo on erotettu yhtä suuri kuin -merkillä (=). Lomakkeessa olevat skandit (ä,ö,å) ja erikoismerkit on koodattu heksadesimaaliluvuiksi ja välilyöntien paikalla on plus-merkki (+) tai %20.
POST-metodia käytettäessä tiedot eivät siirry URL:n mukana, vaan vastaanottavan ohjelman on luettava ne STDIN-muuttujasta. POST-arvoa kannattaa käyttää erityisesti suuren tietomäärän siirtämiseksi lomakkeelta käsittelevälle ohjelmalle. Lomakkeelta siirtyvät tiedot eivät myöskään ole käyttäjän nähtävissä käytettäessä post-metodia. POST-metodia käytetään kun lomake aiheuttaa lisäyksiä, muutoksia tai poistoja
<!DOCTYPE html"> <html> <head> <title>Esimerkkilomake</title> </head> <body> <h1>Esimerkkilomake</h1> <form action="http://palvelin/teepase.cgi" method="post"> <p> <label for="name">Nimi: </label> <input id="name" type="text" name="Nimi" value="Etunimi Sukunimi" /> </p> <p> <label for="email">Email: </label> <input id="email" type="text" name="email" value="Sahköpostiosoite" /> </p> <p> <label for="kommentti">Kommentti: </label> <input id="kommentti" type="text" name="kommentti" value="tähän kommentti" /> </p> <p> <input type="submit" name="laheta" value="Lähetä kommenttisi" /> </p> </form> </body> </html>
Lomake-elementit
WWW-lomakkeille voidaan lisätä hyvin monenlaisia elementtejä, joiden avulla lomakkeista saadaan käyttökelpoisia tehtäväänsä. Erilaisia elementtejä käyttämällä lomakkeesta voidaan saada monipuolinen ja pystytään jopa hieman rajoittamaan käyttäjän antamia syötteitä. Varsin usein lomakkeelle tehdään pelkästään erilaisia tekstikenttiä, mutta muitakin mahdollisuuksia kannattaa toki ajatella.
Seuraavassa listassa on lyhyesti esiteltynä erilaisia lomakekenttiä, joita lomakkeelle voidaan sijoittaa. Kuvauksen perässä on luvun numero, jossa elementtiä käsitellään tarkemmin.
Yksirivinen tekstisyöttökenttä (input type=”text”), johon käyttäjä voi syöttää vapaasti tekstiä yhdelle riville.
Laajempi tekstikenttä (textarea), johon voidaan syöttää tekstiä useammalle riville.
Salasanakenttä (input type=”password”), johon syötettyjen merkkien paikalla näytetään tähtimerkki (*).
Valintaruutu (input type=”checkbox”) on neliön muotoinen kenttä, joita voidaan valita päälle tai pois päältä. Valintaruutuja voidaan valita useampia samasta ryhmästä.
Valintanappi (input type=”radio”) on ympyrän muotoinen kenttä, joka voidaan valita päälle. Valintanappeja voidaan valita ainoastaan yksi samasta ryhmästä.
Lähetyspainike (input type=submit””), jonka avulla kyseisen lomakkeen tiedot lähetetään.
Tyhjennyspainike (input type=”reset”), jolla lomakkeen tiedot saadaan tyhjennettyä tai palautettua oletusarvoille.
Piilokenttä (input type=”hidden”), jolla lomakkeella voidaan viedä tietoja siten, että käyttäjä ei näe niitä selainikkunassa. Tiedot ovat kuitenkin näkyvissä lomakkeen lähdekoodissa, joten elementtiä ei kannata käyttää arkaluontoisten tietojen lähettämiseen.
Valintalista (select) on alasvetovalikko, jolla voidaan toteuttaa erilaisia valintoja lomakkeelle.
Katso myös HTML5:n uudet input-elementin tyypit
Kentän otsikko - label
label-elementti toimii lomake-elementtien otsikkona.
<label>Nimi: <input type="text" name="Nimi" value="Etunimi Sukunimi" /></label>
for-attribuuttia käytetään yhdistämään otsikko varsinaiseen lomake-elementtiin jos lomake-elementtiä ei voida sijoittaa suoraan labelin sisään. Lomake-elementin id-attribuutin ja otsikon for-attribuutin arvojen on oltava samat. Arvojen on oltava yksikäsitteiset, joten otsikko voi viitata ainoastaan yhteen lomake-elementtiin. Seuraavassa esimerkki label-elementin käytöstä:
<label for="name">Nimi: </label><input id="name" type="text" name="Nimi" value="Etunimi Sukunimi" />
accesskey-attribuutin avulla voidaan lomake-elementille määritellä pikanäppäin, jota painamalla siirrytään kenttään, jonka otsikkoon pikanäppäin on määritelty. Yleensä pikanäppäimen kanssa pitää painaa myös jokin toinen näppäin. Tämä näppäin riippuu jonkin verran käytettävästä käyttöjärjestelmästä ja selaimesta. Kts. accesskey (MDN)
<p><label accesskey="N" for="name">Nimi: </label> <input id="name" type="text" name="Nimi" value="Etunimi Sukunimi" /></p>
input-elementti
input-elementti on hyvin monipuolinen lomakkeella käytettävä elementti, jonka type-attribuutin arvoa vaihtamalla saadaan käyttöön erilaisia lomake-elementtejä.
Yleiset ominaisuudet
name-attribuutilla voidaan antaa kontrollille nimi. Nimen antamisen hyöty tulee näkyviin vasta lomakkeen käsittelyn yhteydessä, koska kontrollin arvo lähetetään lomakkeen tiedot käsittelevälle ohjelmalle muodossa name=kentan+sisalto .
value-attribuutilla voidaan kontrollille antaa oletusarvo. Lomakkeen lataamisen yhteydessä value-attribuutin arvo näkyy valmiiksi kontrollissa. Valintaruudun ja valintanapin yhteydessä value-attribuutin arvo välitetään lomakkeen tiedot käsittelevälle ohjelmalle.
Seuraavassa lyhyt esimerkki name- ja value-attribuutin käytöstä. Esimerkissä name-attribuutin arvona on kokonimi ja value-attribuutin arvona on teksti ”Etunimi Sukunimi”.
<input type="text" name="kokonimi" value="Etunimi Sukunimi" />
Jos edellisen esimerkin lomakkeen tiedot lähetetään käsittelevälle ohjelmalle oletusasetuksilla, niin tiedot ovat seuraavaa muotoa (name=value):
kokonimi=Etunimi+Sukunimi
size-attribuutilla voidaan määritellä kontrollille pituus. Pituus annetaan pikseleinä, mutta jos attribuutin type arvona on text tai password, niin arvo tarkoittaa kenttään mahtuvien merkkien lukumäärää.
id-attribuutilla voidaan elementille antaa yksikäsitteinen id-nimi, johon voidaan viitata esimerkiksi label-elementissä.
tabindex-attribuutilla voidaan elementeille määritellä tabulointijärjestys eli järjestys, jossa kentät aktivoituvat painettaessa tab-näppäintä. tabindex-attribuutin arvoksi voidaan antaa numerot välillä 0-32767.
type-attribuutilla määritellään input-elementin käyttötarkoitus. Mahdollisia type-elementin arvoja ovat text, password, checkbox, radio, submit, reset ja hidden.
Tekstikenttä - text
<p><label for="email">Email: </label> <input id=”email” type="text" name="email" value="Sahköpostiosoite" /> </p>
Syöttökentän pituutta ei ole oletuksena rajoitettu, joten riville voi syöttää tekstiä kohtuullisen paljon. Kentän pituutta voidaan rajoittaa maxlength-attribuutin avulla ja näkyvissä olevan tekstikentän koko lomakkeella voidaan määritellä size-attribuutin avulla. Seuraavassa esimerkissä sotun syöttämistä on haluttu rajoittaa. Sotu sisältää yksitoista merkkiä, joten kenttään halutaan tasan yksitoista merkkiä.
<p><label for="sotu">Sotu: </label> <input maxlength="11"size="11" id="sotu" type="text" name="sotu" value="000000-000A" /> </p>
Salasanakenttä - password
<p><label for="passwd">Salasana: </label> <input id="passwd" type="password" name="salasana" value="" /> </p>
Valintaruutu - checkbox
checked-attribuutilla valintaruudulle voidaan määritellä oletusarvo. Tällöin attribuutin arvoksi on laitettava checked.(checked="checked")
<p><label for="henkiloauto">henkilöautolla </label> <input id="henkiloauto" type="checkbox" name="tyomatka" value="hauto" /><br /> <label for="bussi">bussilla </label> <input id="bussi" type="checkbox" name="tyomatka" value="bussi" checked="checked" /><br/> <label for="juna">junalla </label> <input id="juna" type="checkbox" name="tyomatka" value="juna" /><br/> <label for="pp">polkupyörällä </label> <input id="pp" type="checkbox"name="tyomatka" value="pp" /><br/> <label for="mp">moottoripyörällä </label> <input id="mp" type="checkbox"name="tyomatka" value="mp" /><br/> <label for="jalan">kävellen </label> <input id="jalan" type="checkbox" name="tyomatka" value="jalan" /><br/> </p>
Valintanappi - radio
checked-attribuutilla valintaruudulle voidaan määritellä oletusarvo. Tällöin attribuutin arvoksi on laitettava checked. (checked="checked")
<p>Ikäni on</p> <p> <label for="pk20">< 20 vuotta.</label> <input id="pk20" type="radio" name="ika" value="< 20" /><br/> <label for="ika2030">20-30 vuotta.</label> <input id="ika2030" type="radio" name="ika" value="20-30" /><br/> <label for="ika3040">30-40 vuotta</label> <input id="ika3040" type="radio" name="ika" value="30-40" /><br/> <label for="ika4050">40-50 vuotta</label> <input id="ika4050" type="radio" checked="checked" name="ika" value="40-50" /><br/> <label for="sk50">> 50 vuotta</label> <input id="sk50" type="radio" name="ika" value="> 50" /><br/> </p>
Lähetä-painike - submit
submit-arvo luo painikkeen, jolla lähetetään lomakkeen tiedot käsittelevälle ohjelmalle. Painikkeessa lukeva teksti voidaan vaihtaa value-attribuutin arvoa muuttamalla.
<p><input type="submit" name="laheta" value="Lähetä kommenttisi" /> </p>
Tyhjennä-painike - reset
reset-arvo luo painikkeen, jolla lomakkeen kentät tyhjennetään ja kenttiin sijoitetaan oletusarvot. reset-painikkeen käyttöä lomakkeella kannattaa harkita tarkkaan, koska käyttävä voi vahingossa tyhjentää täyttämänsä lomakkeen ennen lähetystä. Älä laita lomakkeelle reset-painiketta
<p><input type="reset" name="tyhjenna" value="Tyhjennä lomake"/></p>
Piilokenttä - hidden
hidden-arvo luo piilotetun kentän, jota ei näytetä käyttäjälle selainikkunassa. Piilotettujen kenttien avulla lomakkeella voidaan välittää tietoa, joka on tarpeellista esimerkiksi lomakkeen käsittelyssä, mutta sitä on turha näyttää varsinaisella lomakkeella. Piilokenttään ei kannata sijoittaa mitään ”salaista” tietoa, kuten esimerkiksi salasanoja tai vastaavia, koska kenttä ja sen arvo nähdään sivun lähdekoodista. Seuraavassa lyhyt esimerkki piilokentän käytöstä.
<p><input type="hidden" name="ID" value="L0011"/></p>
Tekstialue - textarea
textarea-elementti mahdollistaa useampirivisen vapaamuotoisen tekstikentän lomakkeella. Elementtiä kannattaa käyttää erilaisten vapaamuotoisten tekstien kirjoittamispaikkana, koska kirjoittaminen useammalle riville on usein mielekkäämpää kuin yhdelle riville.
name-attribuutilla voidaan antaa textarea-elementille nimi. Kannattaa huomata, että textarea-elementillä ei ole value-attribuuttia, vaan oletussisältö kirjoitetaan elementin sisään ohessa olevan esimerkin mukaisesti.
rows-attribuutti määrittelee textarea-elementissä näkyvillä olevien rivien lukumäärän. Tämä ei kuitenkaan rajoita rivien lukumäärää, joille käyttäjä voi kirjoittaa. Jos kaikki rivit eivät mahdu kerralla textarea-elementin sisään, luodaan elementin oikeaan laitaan vierityspalkki.
cols-attribuutti määrittelee textarea-elementissä olevan rivin pituuden. Rivin pituudella tarkoitettaan riville mahtuvien ”keskiarvokirjainten” määrää. Arvo ei kuitenkaan rajoita riville kirjoitettavien merkkien lukumäärää. Jos rivi ei mahdu kerralla textarea-elementin sisään, luodaan elementin alalaitaan vierityspalkki.
<p><label for="desc">Tarkempi kuvaus ongelmasta</label><br/> <textarea id="desc" name="kuvaus" rows="12" cols="50"> Tähän tarkempi kuvaus asiasta.. </textarea> </p>
Valintalista - select
Valintalista on lomakkeella yksi- tai useampivalintainen alasvetovalikko. Valintalistan käyttötilanteet ovat usein samanlaisia kuin radiopainikkeilla ja valintalaatikoilla, mutta valintalistat vievät fyysisesti paljon vähemmän tilaa lomakkeelta. Valintalista luodaan select-elementillä ja sen sisään täytyy laittaa vähintään yksi option-elementti, josta muodostuu varsinainen valinta.
select-elementti
select-elementti luo varsinaisen valintalistan rungon, jonka sisään tulevat valinnat toteutetaan option-attribuutilla.
name-attribuuttilla voidaan antaa nimi select-elementille.
size-attribuutilla määritellään näkyvissä olevan listan koko. Koko ei ole eri vaihtoehtojen lukumäärä vaan se on pelkästään näkyvillä olevien vaihtoehtojen lukumäärä. Jos vaihtoehtoja on useampia kuin size-attribuutissa on määritelty, niin elementin oikeaan laitaan luodaan vierityspalkki.
multiple-attribuutilla voidaan mahdollistaa elementin useamman vaihtoehdon valinta aktiiviseksi yhtä aikaan. Jos attribuuttia ole määritelty voidaan elementistä kerrallaan valita vain yksi kohta aktiiviseksi.
tabindex-attribuutilla voidaan elementeille määritellä tabulointijärjestys eli järjestys, jossa kentät aktivoituvat painettaessa tab-näppäintä. tabindex-attribuutin arvoksi voidaan antaa numerot välillä 0-32767.
option-elementti
option-elementillä määritellään valintalistan (select-elementin) sisään tulevat vaihtoehdot. Näkyville tuleva vaihtoehto kirjoitetaan option-elementin sisään eli aloitus- ja lopetus-elementin väliin.
selected-attribuutti ilmaisee onko jokin option-elementillä määritelty kohta valittu aktiiviseksi oletuksena. Attribuutin arvoksi pitää antaa selected. (selected=”selected”)
value-attribuutti antaa oletusarvon kontrollille. Jollei kontrollille ole asetettu mitään arvoa, käytetään sen sisältöä oletusarvona.
Seuraavassa esimerkissä on iän kysymiseen tarkoitettu valintalista. Iän oletusarvoksi on määritelty 20-30 vuotta.
<p><label for="ika">Ikäsi on</label> <select id="ika" name="ika"> <option value="pk20">< 20 vuotta</option> <option selected="selected" value="ika2030">20-30 vuotta</option> <option value="ika3040">30-40 vuotta</option> <option value="ika4050">40-50 vuotta</option> <option value="sk50">>50 vuotta</option> </select> </p>
<select id="ika" name="ika" multiple="multiple" size="3">
Valintalistan ryhmittely - optgroup
Valintalistan ryhmittelyyn voidaan käyttää optgroup-elementtiä. Elementillä saadaan kätevästi ryhmiteltyä valintoja pienempiin ja selkeämpiin kokonaisuuksiin.
label-attribuutilla määritellään otsikko koko optgroup-ryhmälle.
<p> <label for="versio">Versio on</label> <select id="versio" name="ohjelma-versio"> <optgroup label="Word"> <option value="Word 6">Word 6</option> <option value="Word 95">Word 95</option> <option value="Word 97">Word 97</option> <option value="Word 2000">Word 2000</option> </optgroup> <optgroup label="Excel"> <option value="Excel 5">Excel 5</option> <option value="Excel 95">Excel 95</option> <option value="Excel 97">Excel 97</option> <option value="Excel 2000">Excel 2000</option> </optgroup> </select> </p>
Lomake-elementtien ryhmittely - fieldset
Seuraavassa esimerkissä on käytetty fieldset-elementtiä lomakkeen tietojen ryhmittelemiseen. legend-elementillä kerrotaan kyseisen elementtiryhmän otsikko, joka on sijoitettu ensimmäiseksi elementiksi fieldset-ryhmään. Lomakkeella voi olla muitakin fieldset-ryhmiä
<fieldset><legend>Henkilötiedot</legend> <label accesskey="N" for="name">Nimi: </label> <input id="name" type="text" name="Nimi" value="Etunimi Sukunimi" /><br /> <label for="email">Email: </label> <input id="email" type="text" name="email" value="Sahköpostiosoite" /><br /> <label for="sotu">Sotu: </label> <input maxlength="11" size="11" id="sotu" type="text" name="sotu" value="000000-000A" /><br /> </fieldset>
Elementtien ryhmän otsikko - legend
Elementtiryhmälle voidaan antaa otsikko legend-elementin avulla.
accesskey-attribuutin avulla voidaan legend-elementille määritellä pikanäppäin, jota painamalla siirrytään kyseisen lomakeryhmän alkuun.
Lomakkeen käsittely
- Selainohjelma pyytää palvelimelta lomakesivun HTTP-protokollan mukaisilla otsikkotiedoilla.
- Palvelin vastaa selaimelle HTTP-protokollan mukaisilla otsikkotiedoilla, jonka jälkeen tarjoaa WWW-sivun datan eli HTML-koodia.
- Käyttäjä täyttää ja hyväksyy lomakkeen. Selain lähettää lomakkeen tiedot WWW-palvelimella suoritettavalle ohjelmalle.
- Lomakkeella oleva data käsitellään ohjelman tekijän haluamalla tavalla.
- Ohjelma palauttaa käyttäjälle virheilmoituksen tai ilmoituksen onnistumisesta, esim. lomakkeen korjauspyynnöillä tai tulossivun.
Lomakkeen käsittely
- Lomaketiedot tulevat GET- tai POST-metodilla.
- GET = lomaketiedot lisätään osoitteen loppuun. Vrt. Googlella tehty haku, jonka voit bookmarkata ja lomakkeen tiedot näkyvät sivun osoitteessa.
- POST = tiedot lähetettään HTTP-pyynnön runko-osassa.
- Käytä GET-metodia tilaa muuttamattomissa pyynnössä, joista voidaan tehdä kirjanmerkki, kuten esim. haut. Lisäykset, poistot, päivitykset ja paljon dataa lähettävät lomakkeet tehdään aina POST-metodilla.
- Tiedot käsitellään WWW-palvelimessa suoritettavalla ohjelmalla
- Ohjelma saa tarvittavat lomaketiedot ja palvelintiedot ympäristömuuttujista. Kokeile
malliohjelmaa, joka tulostaa
ympäristömuuttujien arvot. Kts. Malliohjelman lähdekoodi
CONTEXT_DOCUMENT_ROOT /home/tjlahton/html SERVER_SOFTWARE Apache CONTEXT_PREFIX /~tjlahton SERVER_SIGNATURE <address>Apache Server at users.jyu.fi Port 80</address> REQUEST_METHOD GET SERVER_PROTOCOL HTTP/1.1 QUERY_STRING foo=bar PATH /usr/local/bin:/usr/bin:/bin HTTP_USER_AGENT Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 HTTP_CONNECTION keep-alive SERVER_NAME users.jyu.fi REMOTE_PORT 32051 SERVER_PORT 80 SERVER_ADDR 130.234.10.207 DOCUMENT_ROOT /var/www/virtual.hosts/users.jyu.fi SCRIPT_FILENAME /home/tjlahton/html/cgi-bin/env.cgi SERVER_ADMIN webmaster@cc.jyu.fi HTTP_DNT 1 HTTP_HOST users.jyu.fi SCRIPT_NAME /~tjlahton/cgi-bin/env.cgi REQUEST_URI /~tjlahton/cgi-bin/env.cgi?foo=bar HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 GATEWAY_INTERFACE CGI/1.1 REMOTE_ADDR 130.234.160.35 HTTP_ACCEPT_LANGUAGE en,fi;q=0.7,chrome://global/locale/intl.properties;q=0.3 REQUEST_SCHEME http HTTP_ACCEPT_ENCODING gzip, deflate UNIQUE_ID VrOUbXOFmxsC2sW0mvTPTgAAAAI
- WWW-Palvelimen ja suoritettavan ohjelman välinen rajapinta on määritelty CGI (Common Gateway Interface)-spesifikaatiossa.
- Huomaa, että HTTP on oletuksena tilaton. Emme tiedä edellisistä pyynnöistä tai lomakkeiden käsittelyistä mitään.
HTTP (HyperText Transfer Protocol)
HTTP on protokolla, jonka avulla selain ja WWW-palvelin keskustelevat.
Firefox-selaimen ja WWW-palvelimen välistä HTTP-liikennettä on helppo seurata Firebugilla tai Tamper Data -laajennuksella .
Selain lähettää WWW-palvelimelle pyynnön:
GET /sovellukset/testi.html HTTP/1.1 Connection: keep-alive Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Accept-Encoding: gzip,deflate Accept-Language: en-us,en;q=0.5 Host: appro.mit.jyu.fi Referer: http://appro.mit.jyu.fi/ User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Keep-Alive: 300
GET /sovellukset/testi.html HTTP/1.0 | Pyydetään informaatiota (GET), jonka osoite palvelimella on /sovellukset/testi.html käyttäen HTTP/1.1-protokollaa. |
Connection: keep-alive | Käsketään pitää yhteys päällä. |
Accept: text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8, video/x-mng, image/png, image/jpeg, image/gif;q=0.2, */*;q=0.1 | Luetellaan selaimen ymmärtämät mediatyypit. Kerrotaan myös mitä mediatyyppejä suositaan q-arvojen avulla. |
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 | Luetellaan kelpaavat merkistöt. |
Accept-Encoding: gzip,deflate | Luetellaan tuetut koodaustavat (pakkaus). |
Accept-Language: en-us,en;q=0.5 | Halutut kielet |
Host: appro.mit.jyu.fi | Palvelimen nimi |
Referer: http://appro.mit.jyu.fi/ | Osoite, josta ollaan tulossa (sivu, jolla olevaa linkkiä on klikattu). |
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 | Selaimen tiedot |
Keep-Alive: 300 | Kertoo kuinka monta sekuntia yhteyttä pidetään yllä. Vain HTTP/1.0-protokollassa, mutta käytetään yhteensopivuussyistä. Oikeastaan muoto pitäisi olla Keep-Alive: parametri=arvo. |
Palvelin vastaa:
HTTP/1.1 200 OK Connection: close Date: Tue, 06 Apr 2004 10:53:18 GMT Accept-Ranges: bytes ETag: "2da29-2147-4044819d" Server: Apache/1.3.27 (Unix) (Red-Hat/Linux) PHP/4.1.2 mod_perl/1.26 Vary: Accept Content-Length: 414 Content-Type: application/xhtml+xml; charset=iso-8859-1 Last-Modified: Tue, 02 Mar 2004 12:44:13 GMT <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fi" > <head> <title>Testisivu</title> <link href="testi.css" rel="StyleSheet" type="text/css" /> </head> <body> <h1>Testiotsikko</h1> <p>Testitekstiä</p> </body> </html>
HTTP/1.1 200 OK | Statuskoodi - kaikki kunnossa. |
Connection: close | Palvelin sulkee yhteyden. Normaalisti yhteys on pysyvä (persistent), jotta selain voi tehdä useita pyyntöä (kuvat, css, javascript jne.). |
Date: Tue, 06 Apr 2004 10:53:18 GMT | Päivä ja aika, koska vastaus on lähetetty. |
Accept-Ranges: bytes | Sallitaan tavuina määritellyt pyynnöt joissa halutaan vain osa dokumentista. |
ETag: "2da29-2147-4044819d" | Tunniste. Tunniste muuttuu dokumenttia muutettaessa. |
Server: Apache/1.3.27 (Unix) (Red-Hat/Linux) AxKit/1.62 mod_python/2.7.8 Python/1.5.2 mod_ssl/2.8.12 OpenSSL/0.9.6b DAV/1.0.3 PHP/4.1.2 mod_perl/1.26 mod_throttle/3.1.2 | WWW-palvelimen tiedot |
Vary: Accept-Encoding | Vaihteleeko pyydetty resurssi jonkun ehdon mukaan. Tärkeä tieto esim. välimuisteille. Accept-Encoding: esim. erilainen pakkaus. Accept-Language: tarjolla useita kieliversioita. User-Agent: sivun sisältö riippuu selaimesta. |
Content-Length: 414 | Sisällön koko |
Content-Type: application/xhtml+xml; charset=iso-8859-1 | Mediatyyppi ja merkistö |
Last-Modified: Tue, 02 Mar 2004 12:44:13 GMT | Milloin viimeksi muutettu. |
HTTP-otsikoita voi tutkia tarkemmin esim. seuraavilla ohjelmilla:
- Tamper Data -laajennos Firefoxiin
- Web-Sniffer
HTTP Status Codes
Palvelin palauttaa vastauksessa HTTP-statuskoodin, joka kertoo lyhyesti selaimelle miten pyyntö onnistui ja miten tulee jatkossa toimia. Listassa yleisimmät:
- 200 OK
- 300 Multiple Choices
- 301 Moved Permanently
- 302 Found
- 401 Unauthorized Access
- 403 Forbidden
- 404 Not Found
- 406 Not Acceptable
- 408 Request Time-out
- 500 Internal Server Error
Lisätietoa
Pythonin cgi-kirjasto
HTML:n erikoismerkit (<, > ja &) pitää muistaa koodata entiteeteiksi. Apuna voi käyttää cgi.escape-metodia. Attribuuttien arvot voi koodata xml.sax.saxutils.quoteattr-metodilla.
URLien kielletyt merkit voi koodata urllib.quote-metodilla.
CGI-ohjelmointi Pythonilla
CGI eli Common Gateway Interface on yksinkertaisin rajapinta WWW-sovelluksien tekemiseen
XHTML-dokumentti Python-kielellä ja CGI-rajapinnan kautta tuotettuna:
#!/usr/bin/python # -*- coding: utf-8 -*- print """Content-type: text/html; charset=UTF-8 <!doctype html> <html> <head> <title>Malli</title> </head> <body> <h1>Tulostetaan Pythonilla:</h1> <p> """ print "Hello World! Osaatkönä skändejä?" print """ </p> </body> </html> """
- #!/usr/bin/python kertoo mistä www-palvelimen pitää etsiä käytettävää komentotulkkia eli tässä tapauksessa pythonia
- # -*- coding: utf-8 -*- varmistaa, että lähdekoodi käsitellään UTF-8-merkistönä eikä vahingossakaan esim. ISO-8859-1-muotoisena
- print """Content-type: text/html; charset=UTF-8 Tulostetaan useampi rivi tekstiä jolloin pythonissa käytetään """-merkintää osoittamaan
tulostuksen alku.
Ensimmäiselle riville pitää tulostaa www-selaimen tarvitsema tieto dokumentin mediatyypistä HTTP-otsakkeena (text/html). HTTP-otsakkeen yhteydessä voidaan myös asettaa käytetty merkistö.
Muitakin HTTP-protokollan otsakkeita voitaisiin tulostaa tässä vaiheessa. Varsinainen XHTML-dokumentti alkaa ensimmäisen tyhjän rivin jälkeen.
- """ Monen rivin tuloste loppuu
- print "Hello World!" Tavallinen yhden rivin tulostus
Virheilmoitukset ja asetukset
Pythonilla tehtyjen CGI-ohjelmien debuggaamista helpottaa cgitb-moduulin käyttöönotto:
import cgitb cgitb.enable()
cgitb aiheuttaa virheraporttien näyttämisen www-selaimessa tai niiden tallentamisen tekstitiedostoon.
CGI-ympäristömuuttujat:
import os print "Content-type: text/plain\r\n\r\n"; for param in os.environ.keys(): print "%20s: %s\n" % (param,os.environ[param])
cgi-moduuli
item = form.getvalue("item") if isinstance(item, list): else:
import cgi form = cgi.FieldStorage() user = form.getfirst("user", "").upper() # Ei hajoa vaikka tulisi useampi arvo for item in form.getlist("item"): do_something(item)
HTML:n vaatimien erikoismerkkien koodaukseen voi käyttää cgi.escape(s[, quote])-metodia.
Lisätietoa: HOWTO Use Python in the web
Templatet ja Jinja
Yhtenäisen sivuston eri sivuilla on usein samankaltaisia osia, jotka joudutaan jokaisella sivulla liittämään includella tai copy&pastella jokaiselle sivulle. Näitä osia ovat esimerkiksi navigoinnit ja autentikoinnista huolehtiminen. Entäpä jos joltain sivulta tärkeitä kuten käyttäjätarkistus unohtuukin?
Templateilla (eli sivupohjilla) saavutetaan seuraavia etuja:
- Yhteiset osat kootaan samaan paikkaan
- Yhteiset osat liitetään automaattisesti sivulle
- Sivun tekijän tarvitsee keskittyä ainoastaan sisältöosaan
- Voidaan myös pyrkiä erottamaan ohjelmalogiikka esitystavasta.
- Erotetaan SQL:t ja ohjelmakoodit muualle
- Sivun sisällön, ulkoasun ja bisneslogiikan tuottajat voivat tehdä työtä erikseen
- Ei kannata kuitenkaan pyörää keksiä uudelleen - näiden välillä on aina jonkinlaisia kytköksiä
Sivun sisältämää html-koodia ei pidä kirjoittaa suoraan python-ohjelman sisään, koska silloin tuloksena on ylläpitokelvoton koodin ja html:n sekasotku. Pyritään MVC-malliin jossa ohjelman toimintalogiikka (controller) pidetään erossa näkymästä (view) eli www-sivun sisällöstä. Tämä onnistuu helposti käyttämällä templateja. Yksi käytetyimpiä on Jinja2.
Jinjan koodi erotetaan html-koodista jollakin seuraavista:
- {% ... %} ohjelmakoodi
- {{ ... }} yksittäisen muuttujan tulostaminen html:n sekaan
Muuttujien arvoja voi muokata Jinjan filttereillä. Filtteri ja muuttuja erotetaan toisistaan |-merkillä. Esim. lista|len palauttaa listan pituuden. Jos automatic escaping ei ole päällä niin jää omalle vastuulle varmistaa, että kaikkien muuttujien sisältö kelpaa html:ään. Tämä voidaan varmistaa e-filtterillä: muuttuja|e
Jinjan for-loopissa voi käyttää apuna loop-muuttujan arvoja. Esim. loop.index antaa 1-alkuisen kierroksen indeksin ja loop.index0 0-alkuisen. Jinja silmukkaa ei voi breakata.
Jos tarvii Jinjassa luoda uusia muuttujia niin se on tehtävä set-komennolla:
{% set muuttuja = arvo %}
Katso jinja.cgi-esimerkki (Lähdekoodi, Jinja template)
Toinen jinja-esimerkki (Lähdekoodi, Pohjatemplate, Toinen template)
Python, merkistöt ja erikoismerkit webissä
- Sinun on aina tiedettävä mikä merkistö on merkkijonoissa käytössä. Tämä koskee kaikkia ohjelmointikieliä
- Kirjoita ohjelmakoodi ja sen merkkijonot UTF-8-merkistössä
# -*- coding: utf-8 -*-
- html-dokumentin merkistön on myös oltava UTF-8 (content-type, mahdollinen xml-deklaraatio. mahdollinen meta-elementti, formin accept-charset)
HTTP-otsakkeessa oikea merkistö:
Content-type: text/html; charset=UTF-8
Edelläolevan pitäisi riittää mutta jos merkistö on mainittu jossain muuallakin niin myös siellä UTF-8:
<!doctype html> <html> <head> <meta charset="UTF-8" /> <title>Malli</title> </head> <body> <form action="" method="post" accept-encoding="UTF-8"> </form> </body> </html>
-
Peruskaava on Decode in Encode out
- lomakkeelta tulevat kentät pitää dekoodata unicode-merkkijonoiksi:
form.getfirst("kentta").decode("UTF-8")
- lopullinen tulostettava (webbipalvelimen palauttama) merkkijono on enkoodattava UTF-8-merkistöön
print template.render(hello=teksti).encode("UTF-8")
- lomakkeelta tulevat kentät pitää dekoodata unicode-merkkijonoiksi:
Erikoismerkit webissä
erikoismerkit (<, >, &) hoituvat automaattisesti jos käyttää dom-rajapintaa tai jinjan templateja autoescape-ominaisuuden ollessa päällä. Jos ei käytä niin käyttäjän syötteet on ajettava cgi.escape-funktion läpi. Ei kuitenkaan molempia, koska silloin esim. <-merkki esitetään koodatussa muodossa < eikä <.
Linkkeihin täytyy erikoismerkit (<, >, %amp;, välilyönti, ä,ö,å jne) koodata vielä erikseen, koska linkeissä on omat rajoituksensa. Tämä hoituu urllib.quote-funktiolla.
http://blog.notdot.net/2010/07/Getting-unicode-right-in-Python
http://www.ohjelmointiputka.net/oppaat/opas.php?tunnus=python_l2
Käyttäjien kommentit