#!/home/tjlahton/public_html/cgi-bin/ties4080/venv/bin/python
# -*- coding: UTF-8 -*-
import cgitb
cgitb.enable()
print("""Content-type: text/html; charset=UTF-8\n""")
import cgi
import os
import json
from jinja2 import Template, Environment, FileSystemLoader
import urllib.parse
#yksinkertainen ostoskorisovellus CGI-rajapinnalla. Päivitetty luentovideoversioon
#muuttamalla kaikki merkkijonot unicode-merkkijonoiksi 15.1.2018
#muunnettu python 3 -muotoon 28.1.2021
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({"Tuote": True, "Id":self.id, "Nimi": self.nimi, "Lkm":self.lkm, "Hinta":self.hinta })
# Luokalle voi itse opettaa miten luokka esitetään stringinä. Kts. miten tulostuu
# templaten sisällä.
def __str__(self):
return "Nimi\t"+ self.nimi + "\tLkm:\t" + str(self.lkm) + "\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 {"Tuote": True, "Nimi": o.nimi, "Lkm":o.lkm, "Hinta":o.hinta }
raise TypeError(repr(o) + " 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["Nimi"], o["Lkm"], o["Hinta"])
return o
form = cgi.FieldStorage()
tuote = form.getfirst("tuote", "")
try:
lkm = int(form.getfirst("lkm", 1))
except:
lkm = 1
try:
hinta = double(form.getfirst("hinta", 10.0))
except:
hinta = 10.0
# huom. nyt on vain yksi tuotteet-kenttä lomakkeella
try:
tuotteet = form.getfirst("tuotteet", [])
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("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 )
tallennaurl = urllib.parse.quote_plus( tallenna ) #linkissä käytetty versio
try:
tmpl_path = os.path.join(os.path.dirname(os.environ['SCRIPT_FILENAME']), '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=['jinja2.ext.autoescape'])
except:
env = Environment(autoescape=True, loader=FileSystemLoader(tmpl_path))
template = env.get_template('kori.html')
# tulostetaan lopullinen dokumentti
print(template.render(tuote=tuote, tuotteet=tuotteet, tallenna=tallenna, tallennaurl=tallennaurl))