#!/home/tjlahton/public_html/cgi-bin/ties4080/venv/bin/python
# -*- coding: UTF-8 -*-
#yksinkertainen ostoskorisovellus CGI-rajapinnalla. Päivitetty luentovideoversioon
#muuttamalla kaikki merkkijonot unicode-merkkijonoiksi 15.1.2018
#muunnettu python 3 -muotoon 28.1.2021
#muunnettu flask-sovellukseksi ja tehty yksinkertaistettu versio 9.2.2022
from flask import Flask, request, Response, render_template
import os
import json
import urllib.parse
app = Flask(__name__)
@app.route('/simple', methods=["GET", "POST"])
def simplekori():
form = request.values
tuote = form.get("tuote", "")
lkm = form.get("lkm", 1, type=int)
hinta = form.get("hinta", 10.0, type=float)
tuotteet = form.get("tuotteet", "[]")
# muunnetaan json-muodossa oleva tuotelistaus takaisin pythonin listaksi
try:
tuotteet = json.loads( tuotteet )
except json.decoder.JSONDecodeError:
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ä
lisaa = form.get("lisaa", 0, type=int)
poista = form.get("poista", 0, type=int)
#lisätään jonkin tuotteen määrää
if lisaa:
for t in tuotteet:
if t["id"] == lisaa:
t["lkm"] = t["lkm"] + 1
if poista:
for i in range(len(tuotteet)):
if tuotteet[i]["id"] == poista:
del tuotteet[i]
break
#lisätään uusi tuote
if len(tuote):
#täytyy keksiä uniikki id
max = 1
for t in tuotteet:
if t["id"] >= max:
max = t["id"] + 1
t = {"id": max, "tuote": tuote, "lkm": lkm, "hinta" :hinta}
tuotteet.append(t)
# Muunnetaan lomakkeelle tallennettava tuotteet-lista json-muotoon
# määritellään erotinmerkit ilman välilyöntejä, niin saadaan tiivis muoto
tallenna = json.dumps( tuotteet, separators=(',', ':') )
tallennaurl = urllib.parse.quote_plus( tallenna ) #linkissä käytetty versio
#tehdään siistimpi tulostusasu tuotteelle. Parempi on tehdä jinjassa
def tulosta_tuote(tuote):
return f"Tuote : {tuote['tuote']}\tId:{tuote['id']}\tLukumäärä: {tuote['lkm']}\tHinta: {tuote['hinta']}"
# palautetaan lopullinen dokumentti
return render_template( "simple.html", tuote=tuote, tuotteet=tuotteet, tallenna=tallenna, tallennaurl=tallennaurl, tulosta_tuote=tulosta_tuote)
#monimutkaisempi ostoskori, joka käyttää omaa Tuoteluokkaa
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
@app.route('/', methods=["GET", "POST"])
def kori():
form = request.values
tuote = form.get("tuote", "")
try:
lkm = int(form.get("lkm", 1))
except:
lkm = 1
try:
hinta = double(form.get("hinta", 10.0))
except:
hinta = 10.0
# huom. nyt on vain yksi tuotteet-kenttä lomakkeella
try:
tuotteet = form.get("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.get("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
# tulostetaan lopullinen dokumenttib
return render_template( "kori.html", tuote=tuote, tuotteet=tuotteet, tallenna=tallenna, tallennaurl=tallennaurl)