70 Andmebaasid (front-end)
Kui siiani lisasime ise andmeid andmebaasi, siis nüüd vaatame, kuidas luua veebivorm, nii et kasutaja saab sisestada andmeid ja need lisatakse andmebaasi.
Lisame faili blogi.py meetodid methods=['GET', 'POST']
. Klassi defineerimise järele lisame järgneva rea:
@app.route('/postitused', methods=['GET', 'POST'])
Nüüd lähme html-failide juurde. Meil läheb ka nüüd vaja faili baas.html, mille sisu oli järgnev:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> {% block head %} <title>Minu esimene veebileht</title> {% endblock %} </head> <body> {% block body %} {% endblock %} </body> </html>
Kui seda faili mingil põhjusel veel ei ole, tuleks see kausta templates luua.
Veel loome templates kausta faili blogipostitused.html ja teeme veebivormi. Selleks vajaliku koodi kirjutame body-ossa ehk lisame faili järgneva sisu:
{% extends 'baas.html' %} {% block body %} <h1>Postitused</h1> <h2>Kirjuta uus postitus: </h2> <form action='/postitused' method='POST'> Pealkiri: <input type='text' name='pealkiri' id='pealkiri'> <br> Autor: <input type='text' name='autor' id='autor'> <br> Postitus: <input type='text' name='sisu' id='sisu'> <br> <input type='submit' value='Saada'> </form> {% endblock %}
Siin kirjutasime pealkirjad Postitused ja Kirjuta uus postitus, seejärel lisasime veebivormi osa, kus on lahter nii autori, pealkirja kui ka postituse sisestamise jaoks. Pealkirja lahtrit defineerib näiteks rida Pealkiri: <input type='text' name='pealkiri' id='pealkiri'>
. Lahtrite järel on nupp Saada <input type='submit' value='Saada'>
.
Info kuvamiseks kasutame tsüklit, mille tulemusel kuvatakse kõikide postituste pealkiri, autor ja sisu.
{% for postitus in postitused %} <h2>{{ postitus.pealkiri }}</h2> <h3>Autor: {{ postitus.autor }}</h3> <p>{{ postitus.sisu }}</p> {% endfor %}
Faili blogipostitused.html sisu on nüüd järgnev:
{% extends 'baas.html' %} {% block body %} <h1>Postitused</h1> <h2>Kirjuta uus postitus: </h2> <form action='/postitused' method='POST'> Pealkiri: <input type='text' name='pealkiri' id='pealkiri'> <br> Autor: <input type='text' name='autor' id='autor'> <br> Postitus: <input type='text' name='sisu' id='sisu'> <br> <input type='submit' value='Saada'> </form> {% for postitus in postitused %} <h2>{{ postitus.pealkiri }}</h2> <h3>Autor: {{ postitus.autor }}</h3> <p>{{ postitus.sisu }}</p> {% endfor %} {% endblock %}
Nüüd on vorm olemas ja saame selle siduda andmebaasiga.
Lisame blogi.py failis importimisel request ja redirect.
from flask import Flask, render_template, request, redirect
Nüüd seome vormi andmebaasiga.
@app.route('/postitused', methods=['GET', 'POST']) def blogi(): if request.method == 'POST': p_pealkiri = request.form['pealkiri'] p_autor = request.form['autor'] p_sisu = request.form['sisu'] uus_postitus = Postitus(pealkiri=p_pealkiri, autor=p_autor, sisu=p_sisu) db.session.add(uus_postitus) db.session.commit() return redirect('/postitused') else: koik_postitused = Postitus.query.order_by(Postitus.aeg).all() return render_template('blogipostitused.html', postitused=koik_postitused) # teeb kõik postitused veebis nähtavaks
Faili blogi.py sisu on nüüd järgnev:
from flask import Flask, render_template, request, redirect from flask_sqlalchemy import SQLAlchemy from datetime import datetime app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///postitused.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) class Postitus(db.Model): id = db.Column(db.Integer, primary_key=True) pealkiri = db.Column(db.String(100), nullable=False) sisu = db.Column(db.Text, nullable=False) autor = db.Column(db.String(20), nullable=False, default = 'N/A') aeg = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) def __repr__(self): return 'Postitus ' + str(self.id) @app.route('/postitused', methods=['GET', 'POST']) def blogi(): if request.method == 'POST': p_pealkiri = request.form['pealkiri'] p_autor = request.form['autor'] p_sisu = request.form['sisu'] uus_postitus = Postitus(pealkiri=p_pealkiri, autor=p_autor, sisu=p_sisu) db.session.add(uus_postitus) db.session.commit() return redirect('/postitused') else: koik_postitused = Postitus.query.order_by(Postitus.aeg).all() return render_template('blogipostitused.html', postitused=koik_postitused) # teeb kõik postitused veebis nähtavaks if __name__ == "__main__": app.run()
Kui käivitame app.py programmi Thonnys ja vaatame tulemust aadressilt http://127.0.0.1:5000/postitused, näeb see välja selline:
Nüüd saame postitusi juurde lisada.
Kui lisame failid PythonAnywhere keskkonda, siis kausta mysite lisame failid blogi.py ja postitused.db, alamkausta templates blogipostitused.html ja baas.html.
Järgmisena valime ülevalt menüüst Web ja kerime natuke allapoole, kuni on lehe keskel näha blokk Code jaotus WSGI configuration file ja vajutame vastavale lingile (igaühel on aadressis oma kasutajatunnus, meie näites on aadress /var/www/kasutaja_pythonanywhwere_com_wsgi.py). Seal teeme muudatuse, nii et viimase rea algus oleks from blogi import.
Kui vajab meenutamist, kuidas täpselt tegutseda keskkonnas PythonAnywhere, siis vaata alapeatükki PythonAnywhere. Kui kõik õnnestus, siis peaksime tulemust nägema aadressil https://kasutaja.pythonanywhere.com/postitused, kus sõna kasutaja asemel on igaühe oma kasutajanimi.
Näide arvudega
Nüüd oleme tuttavad näitega, kus sisestatakse teksti, mida kuvatakse veebis. Saame kasutada aga ka teisi andmetüüpe. Järgnevalt vaatame korrutamise näitel, kuidas teha tehteid ja tulemusi kuvada. Kuigi üldiselt hoitakse andmebaasis algandmeid, toome mõlemad näited: esimesel juhul lisatakse andmebaasi arvud, mis korrutatakse, kuid korrutist ei lisata andmebaasi; teisel juhul lisatakse andmebaasi nii arvud kui ka korrutamise tulemus.
Loome väikese andmebaasi arvud.db, kus on üks tabel, milles on kaks arvu, lisaks sisestamise aeg. Selleks loome faili arvutamine.py, kuhu lisame järgneva sisu:
from flask import Flask, render_template, request, redirect from flask_sqlalchemy import SQLAlchemy from datetime import datetime app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///arvud.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) class Arvud(db.Model): id = db.Column(db.Integer, primary_key=True) arv1 = db.Column(db.Integer, nullable=False) arv2 = db.Column(db.Integer, nullable=False) aeg = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) def __repr__(self): return 'Tehe ' + str(self.id)
Kuna tahame, et arvud sisestatakse veebivormi kaudu, siis kirjutame faili arvutamine.py ka vastava funktsiooni. Siin koodis on sees juba ka html-faili nimi arvutamine.html. Selle faili loome hiljem.
@app.route('/arvutamine', methods=['GET', 'POST']) def arvud(): if request.method == 'POST': p_arv1 = request.form['arv1'] p_arv2 = request.form['arv2'] uus_sisend = Arvud(arv1=p_arv1, arv2=p_arv2) db.session.add(uus_sisend) db.session.commit() return redirect('/arvutamine') else: koik_arvud = Arvud.query.order_by(Arvud.aeg).all() return render_template('arvutamine.html', arvud=koik_arvud)
Kõige lõppu lisame arendusserveri ja siluri käivitamise osa.
if __name__ == "__main__": app.run(debug = True, use_debugger = False, use_reloader = False)
Nüüd loome andmebaasi. Kirjutame käsureale from arvutamine import db
, siis Enter ja db.create_all()
.
>>> from arvutamine import db >>> db.create_all()
Kui kõik õnnestus, tekkis arvutamine.py-ga samasse kausta fail arvud.db. Nüüd loome kausta templates faili arvutamine.html (samas kaustas on ka eelnevalt loodud fail baas.html). Kõigepealt kirjutame veebivormi osa.
{% extends 'baas.html' %} {% block body %} <h1>Arvutame</h1> <h2>Sisesta arvud, mida korrutada.</h2> <form action='/arvutamine' method='POST'> 1. arv: <input type='number' name='arv1' id='arv1'> <br> 2. arv: <input type='number' name='arv2' id='arv2'> <br> <input type='submit' value='Saada'> </form>
Seejärel saame kuvada ekraanile sisestatud arvud. Ka korrutamise saame teha siinsamas tsüklis. Sellisel juhul korrutamise tulemust andmebaasi ei lisata.
{% for arv in arvud %} <h2>1. arv: {{ arv.arv1 }}</h2> <h2>2. arv: {{ arv.arv2 }}</h2> <h1>Tulemus on: {{ arv.arv1 * arv.arv2 }}</h1> {% endfor %} {% endblock %}
Nüüd käivitame arvutamine.py faili ja aadressil http://127.0.0.1:5000/arvutamine saab veebivormi kaudu arve sisestada. Kui sisestasime näiteks 2 ja 3, on tulemus järgnev:
Kui me tahame, et korrutis salvestatakse andmebaasi, kirjutame klassi Arvud juurde rea arv3 = db.Column(db.Integer, nullable=False
).
class Arvud(db.Model): id = db.Column(db.Integer, primary_key=True) arv1 = db.Column(db.Integer, nullable=False) arv2 = db.Column(db.Integer, nullable=False) arv3 = db.Column(db.Integer, nullable=False) aeg = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) def __repr__(self): return 'Tehe ' + str(self.id)
Funktsioonis arvud aga lisame rea p_arv3 = int(p_arv1) * int(p_arv2)
ning muudame vastavalt ka järgneva rea muutuja uus_sisend väärtust.
def arvud(): if request.method == 'POST': p_arv1 = request.form['arv1'] p_arv2 = request.form['arv2'] p_arv3 = int(p_arv1) * int(p_arv2) uus_sisend = Arvud(arv1=p_arv1, arv2=p_arv2, arv3=p_arv3) db.session.add(uus_sisend) db.session.commit() return redirect('/arvutamine') else: koik_arvud = Arvud.query.order_by(Arvud.aeg).all() return render_template('arvutamine.html', arvud=koik_arvud) # teeb kõik postitused veebis nähtavaks
Ka failis arvutamine.html saame tsüklis kasutada muutujat arv3.
{% for arv in arvud %} <h2>1. arv: {{ arv.arv1 }}</h2> <h2>2. arv: {{ arv.arv2 }}</h2> <h1>Tulemus on: {{ arv.arv3 }}</h1> {% endfor %}