6. loeng - Veebitehnoloogiad IV: Zope, Plone, Python

Tavaveebist rakendusserverini

Algusaegade veebilehed olid lihtsad - viidetega varustatud tekst ja veidi pilte. Sellise veebisaidi loomiseks oli tavaline HTML täiesti küllaldane. Veebi muutumine ärikeskkonnaks aga pani oma pitseri ka veebitehnoloogiate arengule. Üheks esmaseks tavalise HTMLi puudujäägiks osutus selle staatilisus, s.t. puudus võimalus lihtsate vahenditega muuta veebilehe kujundust ja sisu vastavalt lugeja soovile. Nii hakati kombineerima HTMLi eri programmeerimiskeeltes (tollal eeskätt Perl ja C) loodud skriptidega, mis sisaldasid n.ö. äriloogikat ehk eeskirju erineva sisu ja kujunduse esitamiseks vastavalt etteantud tingimustele. Teiseks suureks probleemiks oli oleku salvestamine - skriptidega tehtud valikud ja nende tulemused läksid seansi lõppedes kaotsi ja tulid järgmisel korral uuesti läbi teha. Nii tulid mängu erinevad andmebaasid - nende tõeline õitseaeg aga algas ilmselt alles siis, kui keerukamat ja kohmakamat CGI tehnoloogiat asendas paindlikum ja lihtsam PHP.

1996. aastal pidi tollase firma Digital Creations töötaja Jim Fulton viima läbi seminari CGI program­meerimisest (mõned allikad väidavad, et ta ei olnud ise CGI-ga varem üldse kokku puutunud, ehkki oli suurte kogemustega programmeerija). Ta korjas kokku hulga erinevate operatsioonide sooritamiseks mõeldud CGI teeke ning kohale jõudes (seminar pidi toimuma teises linnas) oli ta mõelnud välja originaalse viisi veebiobjektide esitamiseks, millest võis saada alternatiiv senisele CGI-le. Tagasiteel sai ta valmis juba osa objektihaldussüsteemist. Digital Creations lõi tema ideede põhjal uue rakendusserverisüsteemi, mille mõned komponendid anti vabalt kasutusse, põhitoode nimega Principia aga jäi kinniseks omandvarasüsteemiks. 1998. aastal tegi aga Hadar Pedhazur, riskikapitalist ja Digital Creationsi üks osanikest, ettepaneku anda kogu süsteemi kood vabaks ja kujundada firma ärimudel ringi oma vaba toote baasil sellega seotud teenuste pakkujaks. Nii tehtigi ning Principiast sai Zope. Järgnes toote populaarsuse kiire kasv, arvuka ja motiveeritud kasutajate kogukonna kujunemine ning Zope'i kasutuselevõtt suurfirmades nagu Red Hat ja CBS, aga ka NASAs ja USA laevastikus.

Zope - mis see on?

Lühidalt öeldes on Zope rakendusserver - dünaamilise veebi loomise ja haldamise vahend. Peamiste omadustena võib välja tuua:

Riistvara poole pealt vajab Zope vähemalt 128MB mälu (väiksemale süsteemile piisab 128MB-st täiesti) ja vähemalt 16MB vaba kettaruumi. NB! Reaalselt vajatav kettaruum on palju suurem, kuna serverisse lisatav materjal võib selle vabalt paisutada gigabaitideni. 16MB kulub puhtalt Zope'i enda vajadusteks. Zope installitakse vaikimisi porti 8080 (tavalise veebiserveri port on harilikult 80), tema FTP-ühendus käib aga pordi 8021 kaudu (tava-FTP port on 21). Seega tuleb sellisele Zope'i veebisaidile viidata koos pordinumbriga - http://www.server.com:8080 . Kui kogu veebisait kasutab Zope'i, siis võib panna selle ka vaikimisi veebiporti või suunata kogu veebiliiklus automaatselt Zope'ile. Veel üheks variandiks on kasutada Zope'i kombinatsiooni mõne teise veebiserveri, näiteks Apache'iga (selline variant on kasutusel ka siin serveris, mistõttu Zope'i kasutavale Kaku Akadeemia veebilehele minnes ei pea pordinumbrit 8080 URLi lisama).

Zope'i rakendused ehk produktid

Zope'i produktid kujutavad endast Zope'i keskkonnas töötavaid rakendusi - need võivad pakkuda lihtsalt mingit lisafunktsionaalsust (andmebaasiliidesed eri baasidele) või olla täiemahulised suured rakenduspaketid (portaalisüsteemid, võrgukaubamajad jms). Produktide andmebaas asub aadressil [L] http://www.zope.org/Products.

Produktide installeerimine on reeglina lihtne, taandudes vaid vastavat produkti sisaldava faili lahtipakkimisele Zope'i produktikataloogi (Zope'i kataloogi alamkataloog lib/python/Products). Mõnel suurel produktil tuleb teha veel täiendavaid installisamme, kuid ka need on harilikult lihtsad.

DTML

DTML (Document Template Markup Language) on Zope'i omalaadne täiendus tavalisele HTMLile. See on HTMLi sarnane märgendikeel, mida saab kõrvuti HTMLiga kasutada Zope'i dokumentide loomisel. DTML-märgendid võivad sisaldada HTMLi - näiteks laialt kasutatav märgend standard_html_header, mida saab edukalt kasutada kõigile veebisaidi lehtedele ühesuguse päise andmiseks. Olgu siin toodud üks võimalik lahendus:


Standard_html_header:

<!DOCTYPE html
     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="et" lang="et">
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-15">
<meta name="generator" content="ise tehtud :)" />
<meta name="author" content="Kaido Kikkas" />
<meta name="classification" content="kodulehekülg" />
<meta name="description" content="Kaku Akadeemia õppematerjal" />
<meta name="keywords" content="Kakk, PHP, SQL, Zope" />
<title>Kaku Akadeemia</title>
<link rel="stylesheet" href="kakk.css" type="text/css" />
</head>
<body>

standard_html_footer:

<p>© 2008 Kakk</p>
</body>
</html>

ja nüüd saame mistahes lehe oma Zope'i veebisaidis luua kohe sellisena (eriti suure efekti annab XHTMLi puhul, kus avapäis on "suur ja kole"):


<dtml-var standard_html_header>
<h1>pealkiri</h1>
<p>Sisu</p>
...
<dtml-var standard_html_footer>

Lisaks võib DTML-märgendites kasutada infot, mis pärineb

Sarnaselt vana HTMLiga ja erinevalt XHTMList kasutab DTML nii üksik- kui paarismärgendeid.

Üheks suure potentsiaaliga võimaluseks on DTMLis kasutada expr-lauses Pythoni programmikoodi - siin võiks ehk mingi paralleeli tõmmata HTMLi ja PHP põimimisele elnevates loengutes. Näiteks saab kasutada DTML-märgendit <dtml-if> ja luua tingimusliku veebilehe - juba tuttava meeste/naiste lehe üldine loogika näeks siis välja nii (paneme tähele topelt-võrdusmärki!):


<dtml-if expr="sugu == 'naine' ">
   See on naiste lehekülg!
<dtml-else>
   See on meeste lehekülg!
</dtml-if>

NB! Lubatud on ka lühikuju - expr-lause ärajätmine ja lihtsalt jutumärkide kasutamine:


<dtml-if "sugu == 'naine'">

Veel ühe näitena võib tuua meilisaatmisvõimaluse, kasutades selleks HTML-vormi, DTML-mootorit ja Zope'i enda meiliserverit (Mailhost) - siin on näiteks tegu enda registreerimisega mingi teeenuse kasutajaks, kus süsteem saadab taotluse edasi läbivaatamiseks. Olgu meil esmalt meilivorm, kuhu kirjutada saadetav sõnum (NB! Kasutame eespool kirjeldatud päise- ja jalusefaili!):


<dtml-var standard_html_header>
                                                                                
<form action="meilimootor" method="post">
<p>Eesnimi: <input type="text" name="eesnimi" size="30"></p>
<p>Perenimi: <input type="text" name="perenimi" size="30"></p>
<p>Aadress: <input type="text" name="aadress" size="50"></p>
<p>Telefon: <input type="text" name="telefon" size="20"></p>
<p>E-post: <input type="text" name="epost" size="30"></p>
<p><input type="submit" value="Saada"></p>
</form>

<standard_html_footer>

Ja nüüd siis fail meilimootor, mis saadab sõnumi ära:


<standard_html_header>

<dtml-sendmail mailhost="MeieMeiliMasin">
To: haldur@teenus.ee
From. <dtml-var epost>
Subject: Tahan registreeruda

Soovin registreeruda Teie teenuse kasutajaks.
Nimi: <dtml-var eesnimi>  <dtml-var perenimi>
Aadress: <dtml-var aadress>
Telefon: <dtml-var telefon>
E-post: <dtml-var epost>
</dtml-sendmail>

<h1>Aitäh, <dtml-var eesnimi>!</h1>

<p>Teie soov on haldurile edastatud.</p>

<dtml-var standard_html_footer>

TAL

DTMLil on heade omaduste kõrval ka puudujääke. Nende seas on Zope Bible'i väitel

Lisada võiks veel kohatise paindumatuse oma HTMLi genereerimisel.

Uus suund alates Zope 2.5-st on lehemallid (Page Templates) ja vastavat XML/XHTML-põhist keelt TAL (Template Attribute Language) ja selle tuletisi (TALES, METAL). Nende lähem vaatlemine jääb paraku ajapuudusel käesolevast loengust välja, soovi korral võib nende kohta lugeda Zope Bookist aadressil [L] http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/AppendixC.stx.

Plone

Põgusa tutvuse võiks teha ka ühe populaarseima Zope'i produktiga - sisuhaldussüsteemiga [L] Plone, mis sündis 1999. aastal kolme programmeerija koostöö viljana ning sai nime ühe vähetuntud bändi järgi, kuid võitis kiiresti populaarsuse seniste valdavalt LAMPi kasutavate süsteemide (PHP-Nuke, Postnuke, Slash jt) kõrval.

Plone'il on Zope'i produktina paljud viimase tugevad küljed - multiplatvormsus, objektipõhisus, modulaarsus jt. Lisaks on Plone algusest peale järginud uusimat XHTML-veebistandardit. Plone on tõlgitud paljudesse keeltesse ning iga kasutaja võib lihtsa vaevaga valida endale keskkonna jaoks sobivaima keele (Plone'isse ülespandud materjali aga muidugi automaatselt ei tõlgita), samuti saab valida erinevate kujunduste ehk "nahkade" (skin) vahel.

Plone on väga laiade võimalustega, kuid elementaarkasutus on lihtne ega nõua kuigivõrd IT-alaseid teadmisi. Lisaks vaikimisi kaasasolevale redaktorile on olemas ka kaks veelgi lihtsamat (Epoz ja Kupu), mis võimaldavad teksti sisestada enam-vähem võrreldavas stiilis tavalise tekstitoimetiga (näit. OpenOffice.org või MS Word).

Kui Zope ja Plone on paigaldatud, on uue portaalifunktsioonidega veebilehe loomine äärmiselt lihtne - piisab vaid "Plone Site" valimisest Zope'i peamenüüst ja paari lahtri täitmisest.

Lisainfot ja ka tutvustava esitluse võib leida [L] Plone'i veebilehelt.

Python

Guido van Rossumi poolt 1991. aasta paiku (eri allikad pakuvad eri numbreid) Hollandi Rahvuslikus Matemaatika ja Arvutiteaduse Instituudis loodud Python on vaba tarkvarana (GPL) interpreteeritav üldotstarbeline programmeerimiskeel (autor ise nimetab seda skriptikeeleks, kuid võrreldes tüüpiliste skriptikeeltega nagu Javascript on Python tunduvalt mahukam). Interpreteeritavus teeb ta sugulaseks Javascripti, PHP, Perli ja ka standardse BASICuga - kõigi nende keelte puhul täidetakse programm jooksvalt lausehaaval (kompileeritava keele nagu C või Pascal puhul teisendatakse kogu programm esmalt masinkoodi ja siis täidetakse). Pythonil on aga olemas ka osaline kompilaator (loob vahekoodi) - tavalise Pythoni faili laiendiks on .py, vahekoodis failil aga .pyc .

Python on objektorienteeritud (võrreldav Java ja C++-ga). Platvormi valik on samuti lai - eri Unixid, Linux, Macintosh, MS-DOS, OS/2 ja Windows. Pythoni nimi ei pärine suurelt kägistavalt maolt, vaid hoopis Monty Pythoni koomikuteseltskonnalt. Oma olemuselt on Python lihtne ja selge (on kohatud ka väidet "Python on selline, nagu BASIC oleks pidanud olema") ja paljud soovitavad teda algajatele esimese keelena.

"Hello World" ja lihtne sisestus

Traditsiooniline kõige lihtsam programm näeb Pythonis välja vägagi lihtne - me ei pea seda isegi eraldi faili kirjutama, vaid tänu interpretaatorile võime selle lause kirjutada otse Pythoni keskkonna käsureale:


>>> print "Tere-tere, maakera!"

Nagu näha, puudub Pythonis C-le ja paljudele teistele keeltele (ka PHP) omane realõputunnus - Python arvestab lauseid reavahetuse järgi (saab ka mitmele reale kirjutada, kuid see tuleb eraldi määrata). Veel enam, Pythonis on oluline ka lause veerupositsioon - seda kasutatakse programmiplokkide tähistamiseks (sellest lähemalt juhtlausete juures).

Lihtsaks infosisestuseks saab kasutada Pythoni standardfunktsiooni raw_input:


nimi = raw_input("Mis su nimi on? ")
print "Tere, ", nimi

Loogika ja andmetüübid

Loogikatehete osas on pilt enam-vähem sama mis teistes keeltes. Nagu C-s ja PHP- tähistatakse võrdust kahe võrdusmärgiga (==), üks võrdusmärk tähistab omistust. Mittevõrdsust saab tähistada nii <> kui ka != .

Python toetab enamikku levinud andmetüüpidest. Arvutüüpidest on kasutusel

Tekstitüüp allub sarnastele põhimõtetele nagu teistes keeltes. Sarnaselt PHP-s nähtuga tuleb tekstisisese jutumärgi või ülakoma ees kasutada kurakaldkriipsu \ :


tekst = "Vanaema ostis \"Philipsi\" tolmuimeja"

Teksti võib vaadelda ka massiivina. Näiteks:


>>> tekst = "Sokid ja saapad"
>>> tekst[6]
'j'
>>> 

Paneme tähele, et massiivi järjestust loetakse ka siin 0-st (väljastati teksti 7. täht)!

Teksti saab kirjutada mitmerealisena jällegi kurakaldkriipsu abil:


>>> print "See on siin üks  \
   jube pikk lause!"

On aga ka parem viis: "kolmekordne jutumärgistus" (võib ka ülakomasid kasutada):


>>> pikklause = """Kogu see pikk jutt siin,
                tuleb ekraanile täpselt nii, 
	  nagu ma ta siia kirjutan - umbes
	nagu HTMLis <pre>-märgendite abil.
	NB! Isegi jutumärke ei ole vaja paosümbolitega
	varustada! N:  Papa "Lada" pani puusse. """

>>> print pikklause
Kogu see pikk jutt siin,
tuleb ekraanile täpselt nii, 
nagu ma ta siia kirjutan - umbes
nagu HTMLis <pre>-märgendite abil.
NB! Isegi jutumärke ei ole vaja paosümbolitega
varustada! N:  Papa "Lada" pani puusse.

>>>

Tekstijuppide liitmine käib +-märgiga. Kui tahta teksti sisse panna arvväärtusi, tuleb see esmalt str-funktsiooniga tekstiks teha:


>>> print "Onu Jüri ostis " + str(5) + " õlut."

Massiivid - muude keelte massiivitüübi sarnaseid tüüpe on Pythonis kaks (kui ka sõnastik massiiviks lugeda, siis 3). Jämedalt võib neid eristada võimaluse järgi neid peale defineerimist ka hiljem muuta.

Esmalt listitüüp võib sisaldada eri tüüpi elemente, lisaks on eraldi funktsioonid nagu append, insert ja del elementidega opereerimiseks. Saab määrata ka listilõikeid ehk väljavõtteid (slice):


>>> yks_list = [1,2,3]
>>> yks_list
[1, 2, 3]
>>> yks_list.append("joru")
>>> yks_list
[1, 2, 3, 'joru']
>>> yks_list.insert(1,"toru")
>>> yks_list
[1, 'toru', 2, 3, 'joru']
>>> del yks_list[1]
>>> yks_list
[1, 2, 3, 'joru']
>>> yks_list[2]
3
>>> yks_list[2:]
[3, 'joru']
>>> yks_list[:2]
[1, 2]
>>>

Teine massiivitüüp, mille ingliskeelsele nimetusele tuple on eesti IT-keelemehed loonud uudisvaste ennik (vt. [L] http://www.imprimaatur.ee/standard/17.htm#17.04.07), on sarnane, kuid teda ei anna pärast defineerimist muuta - sisuliselt on tegu massiivikonstandiga:


>>> yks_ennik = (1,2,3,4,5)
>>> yks_ennik
(1, 2, 3, 4, 5)
>>>

Sõnastikutüüp (dictionary) on võtme ja väärtuse paaridest moodustatud massiivisarnane tüüp:


>>> isik = {'nimi': 'Jyri', 'vanus': 23, 'pikkus': 182, 'jalanumber': 43}
>>> print isik
{'nimi': 'Jyri', 'jalanumber': 43, 'vanus': 23, 'pikkus': 182}
>>> print isik['nimi']
Jyri
>>>

Väärtuse muutmiseks tuleb talle lihtsalt anda uus väärtus, uue võtme lisamiseks tuleb defineerida uus võtme-väärtuse paar:


>>> isik['jalanumber'] = 45
>>> print isik
{'nimi': 'Jyri', 'jalanumber': 45, 'vanus': 23, 'pikkus': 182}
>>> isik['kaal'] = 86
>>> print isik
{'kaal': 86, 'nimi': 'Jyri', 'jalanumber': 45, 'vanus': 23, 'pikkus': 182}
>>>

Sõnastikust eemaldamine käib nagu listiski del-funktsiooniga. Lisaks saab sõnastiku puhul kasutada ka tühjendusfunktsiooni clear, mis kogu sõnastiku tühjendab:


>>> print isik
{'kaal': 86, 'nimi': 'Jyri', 'jalanumber': 45, 'vanus': 23, 'pikkus': 182}
>>> del isik['kaal']
>>> print isik
{'nimi': 'Jyri', 'jalanumber': 45, 'vanus': 23, 'pikkus': 182}
>>> isik.clear()
>>> print isik
{}
>>>

Valik

Tavaline if-lause on väga lihtne:


soov = "Elevant"
pakkumine = raw_input ("Mis looma sa müüd? ")
if pakkumine == soov:
    print "Jaa,  selle ostan kohe ära!"
else:
    print "Päh, seda küll ei taha!"

Näeme siit paari olulist punkti:

Case/switch -mitmendvalik Pythonis puudub, küll aga saab kasutada PHP-ski nähtud elseif-osa, Pythonis on see lühemal kujul elif:


soov = "Elevant"
pakkumine = raw_input ("Mis looma sa müüd? ")
if pakkumine == soov:
    print "Jaa,  selle ostan kohe ära!"
elif pakkumine == "Skunks":
    print "Wäääkkk!! Korista end siit koos tolle haisukotiga!"
else:
    print "Päh, seda küll ei taha!"

Kordused

Pythonis on olemas eelkontrolliga kordus (while) ja fikseeritud kordus (for) - puudub do-while -tüüpi järelkontrolliga kordusetüüp.

Ka korduse juures antakse tsükliskoopi edasi treppimisega:


print "Loeme numbreid:"
while i<=5:
  print i
  i=i+1
print "Ongi loetud!"

Huvitaval kombel kasutatakse Pythonis while-tsüklis ka else-klauslit - see täidetakse viimase lausena enne tsükli töö lõppu:


print "Loeme  numbreid:"
while i<=5:
  print i
  i=i+1
else:
    print "Ongi loetud!"

For-tsükkel on mõnevõrra teistsugune kui mujal, nimelt kasutatakse seda siin pigem massiivi läbimiseks (PHP analoog oleks foreach):


loomad = ['koer', 'kass', 'rott', 'jõehobu']
for loom in loomad:
    print loom
else:
   print "Loomi polegi!"

Tsüklist väljumiseks ja uue kordustakti alustamiseks on nagu PHP-s break ja continue, mida kasutatakse samamoodi.

Viiteid

Application Server Comparison Matrix
Zope.org
Plone.org
Python.org