Python perusteet ja CGI-ohjelmointi

Näissä tehtävissä tutustutaan Pythonin ja CGI-ohjelmoinnin perusteisiin.

users.jyu.fi-palvelimessa on käytössä Python 2.7.7. Jalavassa ja Halavassa on vanhempi Python 2.6.6. Näissä ei ole suurtakaan eroa. Tämän tehtävän tekemisen apuna kannattaa käyttää seuraavia dokumentteja:

Opettele käyttämään myös Pythonin komentotulkin help-komentoa.:

[tjlahton@halava ~]$ python
Python 2.4.3 (#1, Jun 11 2009, 14:09:37) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> help
Type help() for interactive help, or help(object) for help about object.
>>> import cgi
>>> help(cgi)
Help on module cgi:

NAME
    cgi - Support module for CGI (Common Gateway Interface) scripts.
...
...
...

CSS:n vaihtaminen vuodenajan mukaan

Tehtävässä vaihdetaan XHTML-sivun tyylitiedostoa vuodenajasta riippuen. Käytettävät tyylit ovat seuraavat:

  1. Luo haluamallasi editorilla vuodenaika.cgi-tiedosto ja tallenna se W-asemasi juureen cgi-bin/-kansioon.

    Huomaa, että käyttämäsi editorin täytyy osata tallentaa tekemäsi tiedosto käyttäen unix-muotoisia rivinvaihtoja eikä windows-muotoisia. Notepad++ näyttää ikkunan alalaidassa rivinvaihtojen tyypin ja sen voi vaihtaa valinnalla Edit|EOL Conversion|Unix/OSX Format.

    Luo kansio tarvittaessa. HUOM! Kansion täytyy ehdottomasti olla w:\cgi-bin eikä mikään muu. kts. CGI/SSI-tekniikat users.jyu.fi-palvelimella
  2. Kopioi ohjelmasi pohjaksi seuraava koodi:
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    import cgitb
    # seuraava rivi aktivoi cgitb-kirjaston, joka osaa heittää virheilmoitukset www-sivulle
    # näkyville. Ilman tätä virheet menevät www-palvelimen lokiin jonne ei tavallisella
    # käyttäjällä ole pääsyä
    # Jos testaa ohjelmaa komentoriviltä niin seuraava rivi kannattaa kommentoida pois käytöstä
    cgitb.enable()
    import cgi
    import time
    import datetime
    
    
    print """Content-type: text/html; charset=UTF-8
    
    <!DOCTYPE html>
    <html>
    <head>
      <link rel="StyleSheet" href="tyyli.css" type="text/css" />
      <title></title>
    </head>
    <body>
    <h1>Kokeillaan CGI-ohjelmointia</h1>
    <p>Testi</p>
    </body>
    </html>
    """
    
  3. Kokeile ohjelman toimintaa komentorivillä jalava/halava-koneessa.

    Putty-pääteohjelmassa voit kopioida tekstiä leikepöydälle maalaamalla tekstin hiiren vasemmalla painikkeella. Liittäminen tapahtuu oikealla painikkeella tai SHIFT-INSERT-näppäinyhdistelmällä.

    W:-asemallesi pääset seuraavalla komennolla:
    cd /wwwhome$HOME/html
    
    Kannattaa tehdä symbolinen linkki osoittamaan suoraan W:-aseman tiedostoihin:
    ln -s /wwwhome$HOME/html ~/html
    
    niin jatkossa pääsee suoraan komennolla:
    cd html
    

    Suorakäyttö (Unix)

    Toimiakseen ohjelma vaatii suoritusoikeuden (execute) kaikille käyttäjille. Lisäksi ohjelman ryhmän (group) täytyy olla users

    [tjlahton@halava cgi-bin]$ chmod a+x vuodenaika.cgi
    [tjlahton@halava cgi-bin]$ chgrp users vuodenaika.cgi
    [tjlahton@halava cgi-bin]$ ls -al vuodenaika.cgi
    -rwxr-xr-x. 1 tjlahton users 3777 Feb  5 09:59 vuodenaika.cgi

    Cgi-ohjelmaan sekä samaan kansioon EI SAA olla kirjoitusoikeutta muilla kuin käyttäjällä itsellään.

    Jos edellämainitut asiat ovat kunnossa voit kokeilla suorittaa ohjelmasi:

    [tjlahton@jalava cgi-bin]$ ./vuodenaika.cgi 

    Seuraava virhe tarkoittaa, että rivinvaihdot ovat DOS-tyyppisiä vaikka pitäisi olla Unix-tyyppisiä:

     usr/bin/python^M: bad interpreter: No such file or directory

    Varmista, että editorisi käyttää unix-tyylisiä rivinvaihtoja. Varmista myös, että tiedostosi alussa ei ole UTF-8:aan liittyvää BOM-merkintää.

    Komentoriviltä ohjelmaa testattaessa kannattaa yleensä kommentoida pois rivi:

    # cgitb.enable()

    Ja palauttaa tämän taas kun testaa www-selaimella.

    W-asemalla oleviin kansioihin pääset Jalavassa kotisivujen siirtäminen www-palvelimelle-ohjeen avulla.

    Jos ohjelmasi toimii moitteetta komentoriviltä voit kokeilla sitä selaimella osoitteesta:

    http://users.jyu.fi/~omatunnus/cgi-bin/vuodenaika.cgi

    Jos ohjelma ei toimi selaimella eli saat server errorin niin tarkista tietohallintokeskuksen ohje CGI/SSI-tekniikat. Yleensä vikana on, että ohjelman ja kansion ryhmät eivät ole samat. Yleensä ryhmänä pitää olla users.

  4. Notepad++:ssa kannattaa myös muistaa valita käytetty kieli (Python) Language-valikosta, koska Notepad++ ei suoraan .cgi-tiedostopäätteestä pysty sitä päättelemään.
  5. Muuta valmista koodia sen verran, että jaat tulostukset useampaan eri osaan. Ensimmäinen osa tulostaa sivun mediatyypin (content-type) ja tyhjän rivin. Toisessa osassa voit tulostaa sivun alkuosan (head) body-elementtiin saakka ja kolmannessa osassa sivun varsinaisen sisällön eli body-osan. Varmista, että ohjelmasi toimii. Muista jatkossa varmistaa ohjelmasi toiminta tarpeeksi usein. Älä kirjoita liian pitkiä ohjelmakoodipätkiä testaamatta.
  6. Luo ennen head-osan tulostamista merkkijonomuuttuja tyyli ja alusta se tyhjäksi.
  7. Luo lukumuuttuja kuukausi, johon laitat arvoksi meneillään olevan kuukauden numeron. Tämän saat selville seuraavalla tavalla datetime-kirjaston avulla:
    kuukausi = datetime.datetime.now().month

    tai

    tanaan = datetime.datetime.now()
    kuukausi = tanaan.month
  8. Tee seuraavaksi if...elif...else-kontrollirakenne, missä sijoitat halutun tyylitiedoston osoitteen tyyli-muuttujaan meneillään olevan vuodenajan perusteella.
    • Tarkista ensin if-lauseella, onko meneillään talvi. if-lauseen ehdoksi täytyy siis laittaa se, että kuukausi on joko 12, 1 tai 2.
      if kuukausi==12 or kuukausi==1 or kuukausi==2:
          tyyli = "http://www.w3.org/StyleSheets/Core/Oldstyle.css"
      
      HUOM! Pythonissa lohkot merkitään sisentämällä! Sama sisennystaso tarkoittaa siis samaa lohkoa

      Varmista, että editorisi korvaa tabulaattorimerkit neljällä välilyönnillä. Käytä sisennyksessä neljää välilyöntiä. Notepad++:ssa tämä asetus löytyy kohdasta Settings|Preferences|Language

    • Tarkista elif-lauseilla, onko meneillään kevät tai kesä. Kevään kohdalla ehdoksi täytyy siis määritellä, että kuukausi on välillä 3-5 eli suurempi tai yhtäsuuri kuin 3 ja pienempi tai yhtäsuuri kuin 5. Kesän kohdalla vastaava ehto on suurempi tai yhtäsuuri kuin 6 ja pienempi tai yhtäsuuri kuin 8. Alla esimerkki kevään elseif-rakenteesta.
      elif kuukausi >= 3 and kuukausi <= 5:
          tyyli = "http://www.w3.org/StyleSheets/Core/Modernist"
      
    • Aseta lopuksi else-lauseessa tyyli-muuttujan arvoksi syksyn tyylitiedoston osoite.
  9. Nyt oikea tyylitiedoston osoite on tyyli-muuttujassa, eli enää tarvitsee määrittää sivu käyttämään tyylitiedostoa kyseisestä muuttujasta.
    • Tulosta tyylimääritys print-komennolla. Laita tyylin osoitteen paikalle tyyli-muuttujan arvo. Joudut ensin tutustumaan Pythonin merkkijonojen muotoiluun. Korvaa tyylitiedoston osoite tyyli.css merkinnällä %s
      <link rel="StyleSheet" href="%s" type="text/css" />
      Seuraavaksi lisää tulostuksen lopettavan """-merkinnän perään % tyyli:
      """ % tyyli
      Tämä merkintä tarkoittaa, että %s korvataan merkkijonolla, joka saadaan tyyli-muuttujasta. Merkintätapa pitäisi olla tuttu printf- ja sprintf-funktioista esim. C/C++-kielestä.
  10. Kokeile sivun toimintaa selaimella ja korjaa virheet tarvittaessa.
  11. Muuta ohjelmaasi siten, että css-tiedostoa ei valitakkaan kuukauden mukaan vaan se arvotaan satunnaisesti.
    • Tee css-tiedostojen osoitteista lista
    • arvo satunnainen luku nollan ja listan alkioiden lukumäärän väliltä. Tarvitset Pythonin random-kirjastoa.
    • Aseta sivun css-tiedostoksi arvotun luvun osoittama css-tiedosto

Templatet

Ohjelmakoodin ja HTML-koodin kirjoittaminen sekaisin ei ole hyvä idea vaan aiheuttaa vaikeasti ylläpidettävää ohjelmakoodia ja myös alttius virheille kasvaa. Otetaan käyttöön Jinja2-template, jonka avulla voimme sijoittaa html-koodin omaan tiedostoonsa.

Jinja2-templateen voi kirjoittaa ohjelmakoodia. Syntaksi on melkein kuin pythonia mutta ei kuitenkaan. Varmista syntaksi aina Jinjan dokumentaatiosta.

Voit kokeilla mallia tai katsoa malliratkaisun lähdekoodia. Katso myös mallin template

Kokeile käyttää tilan tallentamisen apuna simplejson-kirjastoa. Katso esimerkki ja lähdekoodi. JSON-muodossa voit tallentaa yhteen piilotettuun elementtiin koko listan.

minidom

Myös DOM-rajapintaa voi käyttää apuna. Toteutus on samantapainen kuin Jinjalla mutta kaikki ohjelmakoodi on pidettävä Python-tiedostossa. Voit tutkia myös DOM-version toteutusta.

Toimiva malliratkaisu

Malliratkaisun lähdekoodi

Python DOM ja Templatet-luento

Käyttäjien kommentit

Kommentoi Lisää kommentti
Kurssimateriaalien käyttäminen kaupallisiin tarkoituksiin tai opetusmateriaalina ilman lupaa on ehdottomasti kielletty!
http://appro.mit.jyu.fi/web-sovellukset/ohjaus/ohjaus3/
© Tommi Lahtonen (tommi.j.lahtonen@jyu.fi) <http://hazor.iki.fi/>
2017-02-08 13:54:44
Informaatioteknologia - Jyväskylän yliopiston informaatioteknologian tiedekunta