Andrise programmeerimisalane WIKI

Lisa 2. Näidisrakendus

Kogu teema kokkuvõtteks koostame siinkohal lihtsa näidisrakenduse, mis asub Google App Engine platvormil ja kasutab ära mitmeid Google App Engine võimalusi nagu näiteks andmebaas, memcache ja e-postide saatmine. Tegu on lihtsa külalisteraamatuga, mis oma kirjeid hoiab Google App Engine andmebaasis, kirjutajaid autendib Google Konto abil ning teatab igast lisandunud kirjest aplikatsiooni omanikku e-posti teel.

Aplikatsioon koosneb kokku viiest failist.

  • app.yaml - aplikatsiooni konfiguratsioonifail, siin on kirjas kogu oluline konfiguratsioon
  • index.yaml - andmebaasi indeksite definitsioonid. Kuna kõik päringud on reeglipärased, siis täiendavaid indekse vaja pole ning see fail jääb tühjaks
  • main.py - peamine pogrammifail, mis võtab päringuid vastu ja tegeleb nendega
  • views/index.html - lehemallifail, kus on sees lehe kujundus
  • static/stiilid/leht.css - staatiline CSS fail lehe kujunduse tarbeks

Failide sisu

app.yaml

Fail defineerib ära aplikatsiooni konfiguratsiooni nagu näiteks seade, mis suunab kõik /stiilid/ kataloogi pihta tehtud päringud staatiliste failide juurde vastavas kataloogis, kõik muu aga skriptile main.py

application: kylalised
version: 1
runtime: python
api_version: 1
 
handlers:
 
- url: /stiilid
  static_dir: static/stiilid
 
- url: .*
  script: main.py

index.yaml

Andmebaasi indeksite deklaratsioonid. Kuna aga täiendavaid indekseid pole vaja, jääb see fail oma originaalsele kujule, midagi selles muuta või lisada pole vaja.

indexes:
 
# AUTOGENERATED
 
# This index.yaml is automatically updated whenever the dev_appserver
# detects that a new type of query is run.  If you want to manage the
# index.yaml file manually, remove the above marker line (the line
# saying "# AUTOGENERATED").  If you want to manage some indexes
# manually, move them above the marker line.  The index.yaml file is
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.

main.py

Põhiprogramm, milles asub tegelik loogika. Oskab vastu võtta ainult päringuid "/" aadressile. Juhul kui on tegu GET päringuga, laeb andmebaasist või memcache'st viimased kirjed ja näitab neid brauseris lehemalli abil. Juhul kui on tegu POST päringuga, lisab andmebaasi uue kirje ning kustutab memcache puhvrist vastava elemendi (kuna uue kirje lisamisega muutusid puhvris olevad andmed aegunuks).

#!/usr/bin/env python
# coding: utf-8
 
# süsteemsed teegid
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
import os
 
# andmebaasiteek kirjete salvestamiseks
from google.appengine.ext import db
# memcache teek andmete puhverdamiseks
from google.appengine.api import memcache
# Google Kontod kasutajate tuvastamiseks
from google.appengine.api import users
# Django lehemallid
from google.appengine.ext.webapp import template
# E-posti saatmise teek
from google.appengine.api import mail
 
# andmebaasitabeli kirjeldus
class Kirje(db.Model):
  kasutaja = db.UserProperty(auto_current_user_add = True)  # kes on kirje autor
  pealkiri = db.StringProperty()                            # kirje pealkiri
  sisu = db.TextProperty()                                  # kirje sisu
  aeg = db.DateTimeProperty(auto_now_add = True)            # lisamise aeg
 
 
# Esileht, näitab viimaseid kirjeid külalisteraamatusse
class MainHandler(webapp.RequestHandler):
  # külalisteraamatu vaatamine
  def get(self):
 
    # kontrollime kasutaja andmeid
    kasutaja = users.get_current_user()
 
    # laeme andmed puhvrist
    kirjed = memcache.get("kirjed")
 
    # kui puhvris polnud, laeme andmebaasist
    if kirjed is None:
      # laeme baasist uuemad 100 kirjet
      query = Kirje.all()
      query.order("-aeg")
      kirjed = query.fetch(100)
      memcache.set("kirjed", kirjed)
 
    lehemalli_andmed = {
        "kirjed": kirjed,
        "kasutaja": kasutaja,
        "login_url": users.create_login_url("/"),
        "logout_url": users.create_logout_url("/")
    }
 
    path = os.path.join(os.path.dirname(__file__), 'views/index.html')
    self.response.out.write(template.render(path, lehemalli_andmed))
 
  # külalisteraamatusse postitamine
  def post(self):
 
    # kontrollime kasutaja andmeid
    kasutaja = users.get_current_user()
 
    # juhul kui pole sisse loginud, suuname tagasi
    if not kasutaja:
      self.redirect("/")
      return
 
    # laeme kirje andmed POST parameetritena
    pealkiri = self.request.get("pealkiri")
    sisu = self.request.get("sisu")
 
    # teeme uue andmebaasikirje
    kirje = Kirje()
    kirje.pealkiri = pealkiri
    kirje.sisu = sisu
    kirje.put()
 
    # tühjendame puhvri (kuna lisamisega kirjete sisu muutus
    memcache.delete("kirjed")
 
    # teavitame saidi omanikku
    kiri = mail.EmailMessage()
    # saatja aadress peab olema administraatori aadress, vastasel korral kirja ei saadeta
    kiri.sender = "Peeter Meeter <peeter.meeter@peetermeeter.com>"
    kiri.to = "Peeter Meeter <peeter.meeter@peetermeeter.com>"
    kiri.subject = u"Laekus uus kirje külalisteraamatusse!"
    # kolmekordsed jutumärgid lubavad asetada teksti mitmele reale
    kiri.body = u"""Tere!
Sinu külalisteraamatusse lisati uus kirje:
 
%s (%s)
%s""" % (pealkiri, kasutaja.nickname(), sisu)
    kiri.send()
 
    # suuname tagasi esilehele
    self.redirect("/")
 
def main():
  application = webapp.WSGIApplication([('/', MainHandler)],
                                       debug=True)
  util.run_wsgi_app(application)
 
 
if __name__ == '__main__':
  main()

index.html

Django lehemallifail, mis kuvad andmebaasist laetud kirjed struktureeritult ekraanile. Kontrollib ka sisselogimist - juhul kui on tegu sisseloginud kasutajaga, näidatakse uue kirje lisamise vormi, vastasel korral aga näidatakse vaid sisselogimise linki.

<!DOCTYPE html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Külalisteraamat</title>
  <link rel="stylesheet" media="all" type="text/css" href="/stiilid/leht.css" />
 </head>
 <body>
  <h1>Minu külalisteraamat</h1>
 
  <h2>Viimased kirjed</h2>
 
  {% if kirjed %}
 
   {% for kirje in kirjed %}
   <div class="kirje">
    <p class="pealkiri">
     <strong>{{ kirje.pealkiri|escape }}</strong><br />
     kirjutas {{ kirje.kasutaja.nickname }}
    </p>
    <p class="sisu">{{kirje.sisu|escape|linebreaksbr}}</p>
   </div>
   {% endfor %}
 
  {% else %}
   <p>Ühtegi kirjet veel pole</p>
  {% endif %}
 
  <h2>Jäta oma sissekanne!</h2>
 
  {% if kasutaja %}
   <p>Oled sisse logitud kui <em>{{ kasutaja.nickname }}</em> (<a href="{{logout_url}}">logi välja</a>)</p>
   <form method="post" action="/">
   <table border="0">
    <tr><td>Pealkiri</td><td><input type="text" name="pealkiri" /></td></tr>
    <tr><td>Sisu:</td><td>&nbsp;</td></tr>
    <tr><td colspan="2"><textarea name="sisu" style="width: 100%; height: 100px;"></textarea></td></tr>
    <tr><td>&nbsp;</td><td align="right"><input type="submit" name="nupp" value="Lisa!" /></td></tr>
   </table>
   </form>
  {% else %}
   <p>Kirjeid saavad lisada vaid sisseloginud kasutajad! Sisse saad logida <a href="{{login_url}}">siit</a>.</p>
  {% endif %}
 
 </body>
</html>

leht.css

Lihtne CSS stiilifail, mis seab paika leheküljel kasutatava teksti ja selle suuruse.

body{
    font-family: Arial, Helvetica, Sans-serif;
    font-size: 13px;
    color: #111;
}

Näidisrakenduse demo

Näidisrakendust saab katsetada aadressil http://kylalised.appspot.com/

Terve rakenduse koodi pakituna ühes failis saab alla tõmmata siit: kylalised.zip

Meeles tuleb pidada et kui näidisrakendust kasutada appspot.com serveris, tuleb app.yaml failis aplikatsiooni ID ära muuta. Kohalikus testserveris pole seda vaja teha. Lisaks tuleb ära muuta koodis e-posti saatja ja saaja aadressid - vastasel korral võib server anda kirje lisamisel veateate.