#!/usr/bin/python # -*- coding: UTF-8 -*- import cgitb cgitb.enable() import cgi import os import simplejson as json from jinja2 import Template, Environment, FileSystemLoader #yksinkertainen ostoskorisovellus. Päivitetty luentovideoversioon muuttamalla # kaikki merkkijonot unicode-merkkijonoiksi 15.1.2018 print """Content-type: text/html; charset=UTF-8\n""" class Tuote: ''' Oma luokka tuotteiden ja niiden tietojen käsittelyä helpottamaan Tuo kuitenkin mukanaan vähän lisävaivaa, että saa toimimaan JSON-muodossa ''' # Luokan sisäinen muuttuja jolla saadaan aikaan juokseva tunnistenumero kaikille tuotteille tunniste = 1 def __init__(self, nimi="Tuote", lkm=1, hinta=1): self.nimi = nimi self.lkm = lkm self.hinta = hinta self.id = Tuote.tunniste Tuote.tunniste = Tuote.tunniste + 1 # Python-syntaksin kanssa yhteensopiva string-muotoinen esitys luokasta def __repr__(self): return str({u"Tuote": True, u"Id":self.id, u"Nimi": self.nimi, u"Lkm":self.lkm, u"Hinta":self.hinta }) # Luokalle voi itse opettaa miten luokka esitetään stringinä. Kts. miten tulostuu # templaten sisällä. def __str__(self): return u"Nimi\t"+ self.nimi + u"\tLkm:\t" + str(self.lkm) + u"\tHinta\t" + str(self.hinta) # serialisoi Tuotteen JSONiin sopivaan muotoon def encode_tuote(o): if isinstance(o, Tuote): # palautetaan Tuote-objektin sisältö dictinä, jonka simplejson taas osaa serialisoida return {u"Tuote": True, u"Nimi": o.nimi, u"Lkm":o.lkm, u"Hinta":o.hinta } raise TypeError(repr(o) + u" is not JSON serializable") # deserialisoi JSON-muodon takaisin tuotteeksi def as_tuote(o): if 'Tuote' in o: # Palautetaan dictinä tallennettu Tuote alkuperäiseen muotoonsa return Tuote(o[u"Nimi"], o[u"Lkm"], o[u"Hinta"]) return o form = cgi.FieldStorage() tuote = form.getfirst(u"tuote", "").decode("UTF-8") try: lkm = int(form.getfirst(u"lkm", 1).decode("UTF-8")) except: lkm = 1 try: hinta = double(form.getfirst(u"hinta", 10.0).decode("UTF-8")) except: hinta = 10.0 # huom. nyt on vain yksi tuotteet-kenttä lomakkeella. Jos sitä ei löydy niin halutaan kuitenkin # lista. decode-metodi ei toimi listalle joten hoidettava try...exceptilla try: tuotteet = form.getfirst(u"tuotteet", []).decode("UTF-8") except: tuotteet = [] # muunnetaan json-muodossa oleva tuotelistaus takaisin pythonin listaksi try: if len(tuotteet): # object_hook-määritys tarvitaan, koska serialisoidaan oma luokka # Pythonin perustietotyyppien kanssa ei tarvittaisi object_hook-parametria tuotteet = json.loads( tuotteet, object_hook=as_tuote ) except: tuotteet = [] # Onko kasvatettu ostoskorissa jonkin tuotteen lukumäärää? # vaikka tämä on täysin itse hallinnoitu muuttuja niin silti pitää varautua siihen, että # joku menee sorkkimaan sitä käsin eikä saadakkaan inttiä try: lisaa = int(form.getfirst(u"lisaa", 0)) except: lisaa = 0 if lisaa: for t in tuotteet: if t.id == lisaa: t.lkm = t.lkm + 1 if len(tuote): t = Tuote(tuote, lkm, hinta) tuotteet.append(t) # Muunnetaan lomakkeelle tallennettava tuotteet-lista json-muotoon # on käytettävä apuna itse määriteltyä encode_tuote-funktiota, koska muuten # simplejson ei tiedä miten Tuote-luokka serialisoitaisiin JSON-muotoon # Pythonin perustietotyypit toimisivat suoraan ilman default-parametria tallenna = json.dumps( tuotteet, default=encode_tuote ) try: tmpl_path = os.path.join(os.path.dirname(os.environ[u'SCRIPT_FILENAME']), u'templates') except: # jos tänne päädytään www-palvelimessa niin koko sovellus kaatuu... tmpl_path = "templates" try: env = Environment(autoescape=True, loader=FileSystemLoader(tmpl_path), extensions=[u'jinja2.ext.autoescape']) except: env = Environment(autoescape=True, loader=FileSystemLoader(tmpl_path)) template = env.get_template(u'kori.html') # tulostetaan lopullinen dokumentti print template.render(tuote=tuote, tuotteet=tuotteet, tallenna=tallenna).encode("UTF-8")