from flask import Flask, session, redirect, url_for, escape, request, Response, render_template import hashlib import sys from functools import wraps import sqlite3 import os import werkzeug.exceptions import wtforms from wtforms import Form, BooleanField, StringField, validators, IntegerField, SelectField, widgets, SelectMultipleField, ValidationError, RadioField from flask_wtf_polyglot import PolyglotForm from contextlib import closing app = Flask(__name__) app.debug = True # set the secret key. keep this really secret: app.secret_key = '"\xf9$T\x88\xefT8[\xf1\xc4Y-r@\t\xec!5d\xf9\xcc\xa2\xaa' @app.route('/lomake', methods=['POST','GET']) def lomake(): tiedekunnat = {0:"Valitse tiedekunta", 1:"Humanistinen tiedekunta",2:"Informaatioteknologin tiedekunta", 3:"Kasvatustieteiden tiedekunta", 4:"Liikunta- ja terveystieteiden tiedekunta", 5:"Matemaattis-luonnontieteellinen tiedekunta", 6:"Taloustieteiden tiedekunta", 7:"Yhteiskuntatieteellinen tiedekunta"} kentat = {"etunimi":"","sukunimi":"","tdk":""} errors = dict(kentat) #tekee kopion errors2 = {} kentat2 = {} tehtavia = 9 # lisätään tehtäviä varten errors-dictiin paikat if request.method == 'POST': #varmistetaan, että lomake on lähetetty for k in errors: try: kentat[k] = request.form[k] except KeyError: errors[k] = "!" # ei kelpuuteta välilyöntejä ym. whitespace-merkkejä if not len(kentat[k].strip()): errors[k] = "!" # varmistetaan että tiedekunnan valinta on integer niin voi suoraan vertailla dictin avaimiin try: kentat["tdk"] = int(kentat["tdk"]) except KeyError: kentat["tdk"] = 0 for i in range(1, tehtavia+1): key = "t" + str(i) try: pisteet = request.form[key] except: pisteet = "" errors2[key] = "" kentat2[key] = pisteet try: p = int(pisteet) if p < 0 or p > 5: errors2[key] = "virhe" except: if pisteet != "": errors2[key] = "virhe" return Response( render_template('lomake.html', errors=errors, kentat=kentat, tiedekunnat=tiedekunnat, errors2=errors2, tehtavia=tehtavia, kentat2=kentat2), mimetype='application/xhtml+xml') class MultiCheckboxField(SelectMultipleField): """ A multiple-select, except displays a list of checkboxes. Iterating the field will produce subfields, allowing custom rendering of the enclosed checkbox fields. """ widget = widgets.ListWidget(prefix_label=False) option_widget = widgets.CheckboxInput() @app.route('/wtlomake', methods=['POST','GET']) def wtlomake(): # luodaan lomakeluokka funktion sisällä, jotta voidaan sitä huoletta muokata # myös dynaamisesti. CGI-ohjelmassa toimisi myös globaalina, mutta ei tilanteissa # jossa sovellus jää palvelimen muistiin tiedekunnat = [(0,"Valitse tiedekunta"), (1,"Humanistinen tiedekunta"),(2,"Informaatioteknologian tiedekunta"), (3,"Kasvatustieteiden tiedekunta"), (4,"Liikunta- ja terveystieteiden tiedekunta"), (5,"Matemaattis-luonnontieteellinen tiedekunta"), (6,"Taloustieteiden tiedekunta"), (7,"Yhteiskuntatieteellinen tiedekunta")] class Arvosanalaskuri(PolyglotForm): etunimi = StringField('Etunimi', [validators.InputRequired(), validators.Length(min=2, message="Liian lyhyt etunimi")]) sukunimi = StringField('Sukunimi', [validators.InputRequired(),validators.Length(min=2, message="Liian lyhyt sukunimi")]) #Jos haluat käyttääkin radiobuttoneita niin muuta seuraavaan SelectField-tilalle RadioField. Huom. template voi vaatia myös hieman viilailua jos tekee tämän muutoksen tiedekunta = SelectField('Tiedekunta', choices=tiedekunnat, validators=[validators.InputRequired(message="Virheellinen tiedekunta"), validators.NumberRange(min=1, max=len(tiedekunnat), message="Virheellinen valinta")], coerce=int) #radiobutton-versio tiedekunta_radio = RadioField('Tiedekunta', choices=tiedekunnat, validators=[validators.InputRequired(message="Virheellinen tiedekunta"), validators.NumberRange(min=1, max=len(tiedekunnat), message="Virheellinen valinta")], coerce=int, default=2) tiedekunta_multi = SelectMultipleField('Tiedekunta multi', choices=tiedekunnat, coerce=int,option_widget=widgets.CheckboxInput(), widget=widgets.ListWidget(prefix_label=False)) def validate_tiedekunta_multi(form, field): if not len(field.data): raise ValidationError("Valitse vähintään yksi tiedekunta") for value in field.data: if value < 1 or value > len(tiedekunnat): raise ValidationError("Valitse vähintään yksi tiedekunta") lkm = 10 for t in range(1, lkm+1): setattr(Arvosanalaskuri, "t" + str(t), IntegerField(str(t), validators=[validators.optional(),validators.NumberRange(min=0, max=5, message="Virheellinen arvosana")])) form = Arvosanalaskuri() # validoidaan lomake vasta kun se on oikeasti lähetetty if request.method == 'POST': form.validate() return Response( render_template('wtlomake.html', form=form, lkm=lkm), mimetype="application/xhtml+xml") @app.route('/wtlomake2', methods=['POST','GET']) def wtlomake2(): tiedekunnat = [(0,"Valitse tiedekunta"), (1,"Humanistinen tiedekunta"),(2,"Informaatioteknologian tiedekunta"), (3,"Kasvatustieteiden tiedekunta"), (4,"Liikunta- ja terveystieteiden tiedekunta"), (5,"Matemaattis-luonnontieteellinen tiedekunta"), (6,"Taloustieteiden tiedekunta"), (7,"Yhteiskuntatieteellinen tiedekunta")] class Arvosanalaskuri(PolyglotForm): etunimi = StringField('Etunimi', validators=[validators.InputRequired(),validators.Length(min=2, message="Liian lyhyt etunimi")]) sukunimi = StringField('Sukunimi', validators=[validators.InputRequired(),validators.Length(min=2, message="Liian lyhyt sukunimi")]) tiedekunta = SelectField('Tiedekunta', choices=tiedekunnat, coerce=int) lkm = 10 for t in range(1, lkm+1): setattr(Arvosanalaskuri, "t" + str(t), IntegerField(str(t), validators=[validators.optional(),validators.NumberRange(min=0, max=5, message="Virheellinen arvosana")])) form = Arvosanalaskuri() if request.method == 'POST': form.validate() return Response( render_template('wtlomake2.html', form=form, lkm=lkm), mimetype="application/xhtml+xml") tiedekunnat = [(0,"Valitse tiedekunta"), (1,"Humanistinen tiedekunta"),(2,"Informaatioteknologian tiedekunta"), (3,"Kasvatustieteiden tiedekunta"), (4,"Liikunta- ja terveystieteiden tiedekunta"), (5,"Matemaattis-luonnontieteellinen tiedekunta"), (6,"Taloustieteiden tiedekunta"), (7,"Yhteiskuntatieteellinen tiedekunta")] class Arvosanalaskuri2(PolyglotForm): etunimi = StringField('Etunimi', validators=[validators.InputRequired(),validators.Length(min=2, message="Liian lyhyt etunimi")]) sukunimi = StringField('Sukunimi', validators=[validators.InputRequired(),validators.Length(min=2, message="Liian lyhyt sukunimi")]) tiedekunta = SelectField('Tiedekunta', choices=tiedekunnat, coerce=int) lkm = 10 for t in range(1, lkm+1): setattr(Arvosanalaskuri2, "t" + str(t), IntegerField(str(t), validators=[validators.optional(),validators.NumberRange(min=0, max=5, message="Virheellinen arvosana")])) @app.route('/wtlomake3', methods=['POST','GET']) def wtlomake3(): # Käytettävä samoja attribuuttien nimiä kuin Arvosanalaskuri2-luokassa class Oma(): etunimi = "Tommi_oma_luokka" sukunimi = "Lahtonen_oma_luokka" tiedekunta = 1 oma = Oma() # Jos request.form on olemassa eli lomake on lähetetty niin käytetään sitä # Jos request.formia ei ole niin sitten käytetään oma-objektin sisältöä # jos oma-objektia ei ole annettu niin käytetään data-parametria, joka # kelpuuttaa dictionaryn form = Arvosanalaskuri2(formdata=request.form, obj=oma) # tai # Tässä samat avaimet kuin Arvosanalaskuri2-luokan attribuuttien nimet oletus = {"etunimi": "Tommi_dict", "sukunimi": "Lahtonen_dict", "tiedekunta": 2} form = Arvosanalaskuri2(formdata=request.form, data=oletus) if request.method == 'POST': form.validate() return Response( render_template('wtlomake3.html', form=form, lkm=lkm), mimetype="application/xhtml+xml") if __name__ == '__main__': # debug-moodi ei turvallisuussyistä toimi users.jyu.fi:ssä :-( app.debug = True app.run(debug=True)