{"id":244,"date":"2021-03-05T15:40:40","date_gmt":"2021-03-05T15:40:40","guid":{"rendered":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/?post_type=chapter&#038;p=244"},"modified":"2021-05-06T15:52:47","modified_gmt":"2021-05-06T15:52:47","slug":"otsingumootori-loomine-flaskiga","status":"publish","type":"chapter","link":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/chapter\/otsingumootori-loomine-flaskiga\/","title":{"raw":"Otsingumootori loomine Flaskiga","rendered":"Otsingumootori loomine Flaskiga"},"content":{"raw":"J\u00e4rgneva kahe peat\u00fcki l\u00e4bimiseks on soovitatav eelnevalt l\u00e4bi t\u00f6\u00f6tada Tarkvaraarenduse \u00f5piku 2. tr\u00fcki teema <a href=\"https:\/\/web.htk.tlu.ee\/digitaru\/tarkvara2\/chapter\/flask-sissejuhatus\/\">Veebirakenduse loomine. Flask<\/a>. Seda seet\u00f5ttu, et projekti peat\u00fckid on m\u00f5eldud seal \u00f5pitud Flaski teadmiste ning siin moodulis \u00f5pitud p\u00e4ringute teadmiste kinnistamiseks. Projekti peat\u00fckke saab l\u00e4bida ka ilma Flaski \u00f5ppematerjali uurimata, kuid sellisel juhul tuleb t\u00f5en\u00e4oliselt iseseisvalt ja jooksvalt lisainfot otsida.\r\n\r\nOleme praeguseks omandanud piisavalt teadmisi andmebaaside ja neist p\u00e4rimise kohta. Seega, saame neid ka \u00fche elulise projekti \u2013 otsingumoori loomise \u2013 tarbeks rakendada.\r\n\r\nLoodav otsingumootori on m\u00f5eldud Netflixi andmebaasist teoste mugavaks otsimiseks. Projekt on sobiv on viis p\u00e4ringute reaalsete kasutusalade tutvustamiseks, kuna pea k\u00f5ik internetist leitavad otsingumootorid (sh igasugused v\u00e4iksed otsinguv\u00e4ljad) kasutavad tegelikkuses oma t\u00f6\u00f6ks andmebaasi p\u00e4ringuid.\r\n\r\nKui me varasemates peat\u00fckkides kasutasime 5 faili jaotatud ning eelt\u00f6\u00f6deldud andmeid Netflixi teoste kohta, siis selle projekti raames kasutame lihtsuse nimel vaid algandmeid. Neid laeme alla aga hiljem.\r\n<h2>Tarkvara installimine ja moodulite paigaldamine<\/h2>\r\nEsmalt on soovitatav installida arenduskeskkond Thonny. Soovi korral leiab selleks juhendeid Programmeerimise \u00f5piku peat\u00fcki Sissejuhatus alampeat\u00fckist <a href=\"https:\/\/web.htk.tlu.ee\/digitaru\/programmeerimine\/chapter\/programm\/\">Programm<\/a>.\r\n\r\nP\u00e4rast Thonny installimist on tarvis paigaldada kaks moodulit \u2013 <em>Flask<\/em> ja <em>Flask-SQLAlchemy<\/em>.\r\n\r\n<em>Flask<\/em>-i mooduli paigaldamiseks tuleb k\u00f5igepealt valida Thonny men\u00fc\u00fcst <em>Tools \u2192 Manage Packages<\/em>. Seej\u00e4rel tuleb otsinguaknasse kirjutada <em>Flask<\/em> ning klikata nupule <em>Search on PyPi<\/em>. P\u00e4rast seda tuleb vajutada valikule <em>Flask<\/em> ning seej\u00e4rel nupule <em>Install<\/em>.\r\n\r\nMooduli <em>Flask-SQLAlchemy<\/em> installimine k\u00e4ib identselt.\r\n\r\nMooduliga <em>Flask-SQLAlchemy<\/em> tuleb automaatselt kaasa ka moodul <em>SQLAlchemy<\/em>. K\u00e4esoleva \u00f5ppematerjali koostamise ajal oli selle v\u00e4rskeim (ametlikult) stabiilne versioon 1.4.1. Selle versiooniga esineb andmebaasiga \u00fchendust luues probleeme. Seega tuleb mooduli <em>SQLAlchemy<\/em> versiooni langetada.\r\n\r\nMooduli versiooni langetamiseks tuleb <em>Manage Packages<\/em> vaatest esmalt moodul <em>SQLAlchemy<\/em> vasakult listist \u00fcles otsida ning seej\u00e4rel sellele klikata. Avanenud vaates tuleb vajutada nupule '<em>...'<\/em>, nii nagu alloleval pildil.\r\n\r\n<img class=\"alignnone size-full wp-image-737\" src=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/1.png\" alt=\"Mooduli versiooni langetamise esimene samm\" width=\"667\" height=\"458\" \/>\r\n\r\nSeej\u00e4rel tuleb valida soovitud versioon, milleks on viimane kindlalt t\u00f6\u00f6tav versioon 1.3.23 ning l\u00f5puks tuleb klikata nupul <em>Install<\/em>.\r\n\r\n<img class=\"alignnone size-full wp-image-738\" src=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/2-1.png\" alt=\"Mooduli versiooni langetamise teine samm\" width=\"185\" height=\"210\" \/>\r\n\r\nP\u00e4rast seda avaneb laadimisribaga aken ning laadimise l\u00f5ppedes on mooduli versioon langetatud. V\u00f5imalik, et l\u00f5pus n\u00e4idatakse \u00f5igustega seotud veateadet, kuid see ei ole siinkohal \u00fcldjuhul t\u00e4henduslik ning versiooni langetamine peaks siiski t\u00f6\u00f6tama.\r\n\r\nN\u00fc\u00fcd ongi tarkvara edukalt installitud ning vajalikud moodulid paigaldatud.\r\n<h2>Algse programmi loomine<\/h2>\r\nAlustuseks tuleks meeldivasse asukohta luua kaust, kuhu hakkame omakorda projektiga seotud faile looma.\r\n\r\nAlustame sellega, et loome oma Flaski programmi aluse, mis renderdab aadressile <a href=\"http:\/\/127.0.0.1:5000\/teosed\">127.0.0.1:5000\/teosed<\/a> faili <code>teosed.html<\/code> sisu. Faili <code>teosed.html<\/code> veel ei eksisteeri, kuid ka selle loome peatselt.\r\n\r\nPaneme meie programmi alusfaili nimeks <code>app.py<\/code> ning olgu selle sisu j\u00e4rgnev:\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">from flask import Flask, render_template\r\n\r\napp = Flask(__name__)\r\n\r\n@app.route('\/teosed')\r\ndef teosed():\r\n\u00a0\u00a0\u00a0 return render_template('teosed.html', teosed=[])\r\n\r\nif __name__ == \"__main__\":\r\n\u00a0\u00a0\u00a0 app.run()<\/pre>\r\n<code><\/code>\r\n\r\nSelleks, et me loodud faili ka jooksutada saaks, tuleks n\u00fc\u00fcd luua fail <code>teosed.html<\/code> ning selle baasfail <code>baas.html<\/code>. Failid <code>teosed.html<\/code> ja <code>baas.html<\/code> tuleks paigutada projekti kausta alamkausta <code>templates<\/code>, mis tuleb samuti siinkohal luua.\r\n\r\nProjekti kaust peaks hetkeseisuga v\u00e4lja n\u00e4gema selline:\r\n\r\n<img class=\"alignnone size-full wp-image-1163\" src=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust1.png\" alt=\"Projekti kausta \u00fclesehitus 1\" width=\"594\" height=\"65\" \/>\r\n\r\nLoome esimesena faili baas.html, kuna fail teosed.html p\u00f5hineb osaliselt sellel. Olgu faili <code>baas.html<\/code> sisu j\u00e4rgnev:\r\n\r\n<code><\/code>\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n    &lt;meta charset=\"UTF-8\"&gt;\r\n    {% block head %} &lt;title&gt;Otsingumootor&lt;\/title&gt; {% endblock %}\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n    {% block body %} {% endblock %}\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\r\n<code><\/code>\r\n\r\nLoodud fail t\u00e4psustab hetkel peamiselt seda, et k\u00f5igi muude <code>.html<\/code> failide pealkiri olgu Otsingumootor juhul, kui seda pole neis failides \u00fcle kirjutatud.\r\n\r\nN\u00fc\u00fcd saame luua ka faili <code>teosed.html<\/code>, mille sisu olgu j\u00e4rgnev:\r\n\r\n<code><\/code>\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">{% extends 'baas.html' %}\r\n{% block body %}\r\n&lt;h1&gt;Teosed&lt;\/h1&gt;\r\n&lt;table&gt;\r\n    &lt;tr&gt;\r\n        &lt;th&gt;Pealkiri&lt;\/th&gt;\r\n        &lt;th&gt;T\u00fc\u00fcp&lt;\/th&gt;\r\n        &lt;th&gt;Riigid&lt;\/th&gt;\r\n        &lt;th&gt;Aasta&lt;\/th&gt;\r\n        &lt;th&gt;\u017danrid&lt;\/th&gt;\r\n        &lt;th&gt;N\u00e4itlejad&lt;\/th&gt;\r\n        &lt;th&gt;Kirjeldus&lt;\/th&gt;\r\n    &lt;\/tr&gt;\r\n    {% for teos in teosed %}\r\n        &lt;tr&gt;\r\n            &lt;td&gt;{{ teos.pealkiri }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.tuup }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.riigid }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.valjalaske_aasta }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.zanrid }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.naitlejad }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.kirjeldus }}&lt;\/td&gt;\r\n        &lt;\/tr&gt;\r\n    {% endfor %}\r\n&lt;\/table&gt;\r\n{% endblock %}<\/pre>\r\n<code><\/code>\r\n\r\nFailis <code>teosed.html<\/code> t\u00e4psustame esmalt seda, et viitame failile <code>baas.html<\/code>. Seej\u00e4rel alustame <code>body<\/code> plokiga, mille sisse loome teoste tabeli. Tabeli veergude pealkirjad m\u00e4\u00e4rame k\u00e4sitsi, kuid tabelis kuvatavad andmeread tulevad argumendist <code>teosed<\/code>. M\u00e4letatavasti andsime failis <code>app.py<\/code> failile <code>teosed.html<\/code> hetkel ette t\u00fchja listi, seega on tabel t\u00fchi.\r\n\r\nProjekti kausta alamkausta <code>templates<\/code> sisu peaks hetkeseisuga v\u00e4lja n\u00e4gema selline:\r\n\r\n<img class=\"alignnone size-full wp-image-1164\" src=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust2.png\" alt=\"Projekti kausta templates \u00fclesehitus\" width=\"595\" height=\"64\" \/>\r\n\r\nKui k\u00f5ik failid on loodud, v\u00f5ib jooksutada faili <code>app.py<\/code>. Seni valminud programmi tulemust saab brauseri abil vaadata aadressil <a href=\"http:\/\/127.0.0.1:5000\/teosed\">127.0.0.1:5000\/teosed<\/a> v\u00f5i <a href=\"5000\/teosed\">localhost:5000\/teosed<\/a>.\r\n<h2>Andmebaasi ja selle tabeli loomine ning andmetega t\u00e4itmine<\/h2>\r\nSelleks, et loodud tabelis andmeid kuvada saaks, tuleb luua andmebaas ning selle sisse Netflixi teoste andmeid hoiustav tabel. Esmalt tuleb hakata t\u00e4iendama faili <code>app.py<\/code>.\r\n\r\nLisame importide hulka j\u00e4rgneva rea, mille abil impordime andmebaasiga suhtlemiseks kasutatava mooduli <em>SQLAlchemy<\/em>:\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">from flask_sqlalchemy import SQLAlchemy<\/pre>\r\nSeej\u00e4rel tuleks p\u00e4rast rida\u00a0<code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">app = Flask(__name__)<\/code> lisada kolm andmebaasi loomise ja seadistamisega seotud koodirida:\r\n\r\n<code><\/code>\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:\/\/\/teosed.db'\r\napp.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\r\ndb = SQLAlchemy(app)<\/pre>\r\n<code><\/code>\r\n\r\nEsimese reaga m\u00e4\u00e4rame andmebaasi faili salvestamise asukoha. Kasutatud kirjapilt t\u00e4hendab seda, et fail <code>teosed.db<\/code> luuakse failiga <code>app.py<\/code> samasse kausta. Teise reaga m\u00e4\u00e4rame, et ei soovi muudatusi j\u00e4lgida ning kolmanda reaga loomegi andmebaasi.\r\n\r\nEsimeses reas v\u00f5is m\u00e4rgata s\u00f5na <em>sqlite<\/em>. See viitab sellele, et me kasutame andmebaasi juhtimiss\u00fcsteemina <em>SQLite<\/em>'i, mitte <em>PostgreSQL<\/em>'i, nagu oleme teinud siiani. <em>SQLite<\/em> on t\u00f5en\u00e4oliselt enim kasutatud andmebaasi juhtimiss\u00fcsteem maailmas, kuna see on mahult v\u00e4ike, lihtne ning v\u00e4ga paljudesse programmidesse sisse ehitatud. Seega sobib ta h\u00e4sti ka meie v\u00e4ikese projekti jaoks. Soovi korral v\u00f5ib <em>SQLite<\/em>'i kohta juurde lugeda selle <a href=\"https:\/\/www.sqlite.org\/index.html\">kodulehelt<\/a>.\r\n\r\nKuna me kasutame andmebaasiga suhtlemiseks niikuinii moodulit <em>SQLAlchemy<\/em> ei m\u00f5juta meid eriti see, milline andmebaasi juhtimiss\u00fcsteem selle taga on. Seega v\u00f5iksime kasutada endiselt <em>PostgreSQL<\/em>'i, kuid see teeks seadistamise m\u00f5nev\u00f5rra keerukamaks.\r\n\r\nJ\u00e4rgmise sammuna tuleks loodud andmebaasi luua tabel Teosed, milles hakkame hoiustama k\u00f5iki teostega seotud andmeid. Enne seda tuleks aga tutvuda meie algandmetega, mis on p\u00e4rit <a href=\"https:\/\/www.kaggle.com\/shivamb\/netflix-shows\">siit<\/a>. Varasemates peat\u00fckkides kasutasime t\u00f6\u00f6deldud versiooni samadest andmetest.\r\n\r\nN\u00fc\u00fcd tuleks andmed ka alla laadida. Seda v\u00f5ib teha ka andmete algallikast, kuid vigade v\u00e4ltimiseks on seda soovitatav teha <a href=\"https:\/\/drive.google.com\/file\/d\/15Dtbeo5VJIc0vRjSL07XuFGIM2UTG1Ew\/view?usp=sharing\">siit<\/a>. Andmetega t\u00f6\u00f6tame t\u00e4psemalt edasi p\u00e4rast tabeli loomist.\r\n\r\nSelleks, et tabel Teosed luua, t\u00e4iendame taaskord faili <code>app.py<\/code>. J\u00e4rgnevad read tuleks lisada faili p\u00e4rast andmebaasi loomise osa:\r\n\r\n<code><\/code>\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">class Teosed(db.Model):\r\n    id = db.Column(db.String(10000), primary_key=True)\r\n    tuup = db.Column(db.String(7), nullable=False)\r\n    pealkiri = db.Column(db.String(150), nullable=False)\r\n    lavastajad = db.Column(db.Text)\r\n    naitlejad = db.Column(db.Text)\r\n    riigid = db.Column(db.Text)\r\n    lisamise_kuupaev = db.Column(db.String(100))\r\n    valjalaske_aasta = db.Column(db.Integer, nullable=False)\r\n    vanusepiirang = db.Column(db.String(20))\r\n    kestus = db.Column(db.String(20), nullable=False)\r\n    zanrid = db.Column(db.Text, nullable=False)\r\n    kirjeldus = db.Column(db.String(500), nullable=False)\r\n    def __repr__(self):\r\n        return 'Teos: ' + str(self.pealkiri)<\/pre>\r\n<code><\/code>\r\n\r\nEsimese reaga t\u00e4psustame tabeli nime ning selle, millise andmebaasiga see seotud on.\r\n\r\nJ\u00e4rgmised 12 rida t\u00e4histavad tabeli veerge ehk tunnuseid. Nagu n\u00e4ha, siis tuleb primaarv\u00f5tme t\u00e4psustamiseks kirjutada <code>primary_key=True<\/code> ning selleks, et mitte lubada v\u00e4\u00e4rtusi <code><span style=\"color: #000080\"><strong><span style=\"color: #970000\">NULL<\/span><\/strong><\/span><\/code>, tuleb kirjutada <code>nullable=False<\/code>.\r\n\r\nAndmet\u00fc\u00fcpidena kasutame siinkohal <code>String<\/code>'i, <code>Text<\/code>'i ja <code>Integer'<\/code>i. Seega erinevad need m\u00f5nev\u00f5rra seni kasutatust. Kui me <em>PostgreSQL<\/em>'s kasutasime s\u00f5ne t\u00fc\u00fcpi v\u00e4\u00e4rtuste jaoks andmet\u00fc\u00fcpi <code><span style=\"color: #000080\"><strong>VARCHAR<\/strong><\/span><\/code>, siis n\u00fc\u00fcd tuleb kasutada andmet\u00fc\u00fcpi <code>String<\/code>. Pikkuse t\u00e4psustamine k\u00e4ib aga identselt. Andmet\u00fc\u00fcp <code>Text<\/code> t\u00e4histab teadmata pikkusega s\u00f5nesid ning <code>Integer<\/code> t\u00e4histab t\u00e4isarve, nagu ikka.\r\n\r\nViimase kahe koodireaga t\u00e4psustame seda, kuidas k\u00e4surealt selle tabeli andmeid p\u00e4rides igat andmerida p\u00e4ringu tulemuses kujutatakse. Kasutatud kirjapilt t\u00e4hendab seda, et pika andmerea asemel kuvatakse lihtsalt n\u00e4iteks 'Teosed: The Queen's Gambit'.\r\n\r\nN\u00fc\u00fcd on meil v\u00f5imalik andmebaas ning selle sees olev tabel Teosed p\u00e4riselt mingisse faili luua. Selleks kasutame Thonny k\u00e4surida. Kui k\u00e4surida pole juba n\u00e4htaval, vali \u00fclevalt men\u00fc\u00fcst <em>View<\/em> <em>\u2192 <\/em><em>Shell<\/em>, p\u00e4rast mida peaks k\u00e4surida koodivaate all avanema.\r\n\r\nK\u00e4ivita fail <code>app.py<\/code>, kui sa pole seda juba teinud. Soovi korral uuri veebilehte <a href=\"http:\/\/127.0.0.1:5000\/teosed\">127.0.0.1:5000\/teosed<\/a> ning seej\u00e4rel peata fail.\r\n\r\nAndmebaasi ja tabeli loomiseks kirjuta k\u00e4suritta j\u00e4rjest (kuid v\u00e4ikese vahega) j\u00e4rgnevad k\u00e4sud:\r\n<ol>\r\n \t<li><code><code><code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">from app import db<\/code><\/code><\/code><code><code><\/code><\/code><\/li>\r\n \t<li><code><code><code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">db.create_all()<\/code><\/code><\/code><code><\/code><\/li>\r\n<\/ol>\r\nN\u00fc\u00fcd saame kontrollida, kas projekti kausta tekkis andmebaasi fail <code>teosed.db<\/code>. Kui jah, on k\u00f5ik h\u00e4sti. Kui ei, vaata hoolikalt \u00fcle senised sammud ja proovi need uuesti l\u00e4bi teha.\r\n\r\nKuna andmebaas ja teoste tabel on n\u00fc\u00fcd loodud, saame andmeid tabelisse lisama hakata. Kui andmed pole juba alla laetud, tuleks seda n\u00fc\u00fcd teha. Seej\u00e4rel tuleb allalaetud kokkupakitud andmed lahti pakkida ning projekti kausta t\u00f5sta. L\u00f5puks tuleb luua ka uus koodifail <code>abi.py<\/code>. Nii andmefail kui ka koodifail peaksid paiknema samal tasandil mis <code>app.py<\/code>.\r\n\r\nFaili <code>abi.py<\/code> paneme koodi, mille abil lisatakse failis <code>netflix_titles.csv<\/code> olevad andmed andmebaasi faili <code>teosed.db<\/code>.\r\n\r\nOlgu faili <code>abi.py<\/code> sisu j\u00e4rgnev:\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">import csv, sqlite3\r\n\r\ncon = sqlite3.connect(\"C:\/Users\/Kasutaja\/Desktop\/L\u00f5put\u00f6\u00f6\/Otsingumootor_jooksev\/teosed.db\")\r\ncur = con.cursor()\r\n\r\nwith open('netflix_titles.csv','r', encoding='utf8') as f:\r\n    dr = csv.DictReader(f)\r\n    andmeread = [(i['show_id'], i['type'], i['title'], i['director'], i['cast'], i['country'], i['date_added'],\r\n    i['release_year'], i['rating'], i['duration'], i['listed_in'], i['description'])\r\n    for i in dr]\r\n\r\ncur.executemany(\"INSERT INTO Teosed (id, tuup, pealkiri, lavastajad, naitlejad, riigid, lisamise_kuupaev, valjalaske_aasta, vanusepiirang, kestus, zanrid, kirjeldus) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);\",\r\nandmeread)\r\ncon.commit()\r\ncon.close()<\/pre>\r\n<strong>Muuda<\/strong> enne j\u00e4tkamist koodireas\u00a0<code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">con = sqlite3.connect(\"C:\/Users\/Kasutaja\/Desktop\/L\u00f5put\u00f6\u00f6\/Otsingumootor_jooksev\/teosed.db\")<\/code>\r\nn\u00e4idatud failitee enda projektile vastavaks!\r\n\r\nKuna tegemist on vaid abifailiga, ei keskendu me siinkohal selle t\u00f6\u00f6p\u00f5him\u00f5tetele. Soovi korral saab aga <a href=\"https:\/\/docs.python.org\/3\/library\/sqlite3.html\"><em>sqlite3<\/em> dokumentatsioonist<\/a> uurida n\u00e4iteks seda, mida t\u00e4hendavad koodis kasutatud <em>Connection<\/em> ja <em>Cursor<\/em>.\r\n\r\n<strong>Jooksuta<\/strong> n\u00fc\u00fcd faili <code>abi.py<\/code>, mille tulemusena lisatakse k\u00f5ik <code>.csv<\/code> failis olevad andmed meie andmebaasi!\r\n\r\nViimaks, et meie andmebaasis olevaid andmeid ka aadressil <a href=\"http:\/\/127.0.0.1:5000\/teosed\">127.0.0.1:5000\/teosed<\/a> kuvataks, tuleb faili <code>app.py<\/code> meetodit <code>teosed()<\/code> veidi kohandada. Muuda see j\u00e4rgnevaks:<code><\/code><code><\/code>\r\n<code><\/code>\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">@app.route('\/teosed')\r\ndef teosed():\r\n    koik_teosed = Teosed.query.all()\r\n    return render_template('teosed.html', teosed=koik_teosed)<\/pre>\r\n<code><\/code>\r\n\r\n<code><\/code>\r\n\r\nSelle tulemusena p\u00e4ritakse muutujasse <code>koik_teosed<\/code> tabeli Teosed kogu sisu. Muutja <code>koik_teosed<\/code> v\u00e4\u00e4rtuse anname omakorda edasi failile <code>teosed.html<\/code>. M\u00e4letatavasti kasutati failis <code>teosed.html<\/code> argumendi teosed v\u00e4\u00e4rtust tabeli andmetega t\u00e4itmiseks.\r\n\r\nJooksuta n\u00fc\u00fcd uuesti faili <code>app.py<\/code> ning peaksid aadressil <a href=\"http:\/\/127.0.0.1:5000\/teosed\">127.0.0.1:5000\/teosed<\/a> n\u00e4gema k\u00f5igi teoste andmeid. Kuigi andmebaasi tabelis oli veerge 12, on veebilehel neid k\u00f5igest 7. See on nii, kuna me t\u00e4psustasime failis <code>teosed.html<\/code> vaid 7 veeru nimed, mille v\u00e4\u00e4rtuseid me n\u00e4ha soovime.\r\n\r\nJ\u00e4rgmises peat\u00fckis kujundame oma projekti v\u00e4limust ning lisame erinevaid otsingufunktsionaalsusi.","rendered":"<p>J\u00e4rgneva kahe peat\u00fcki l\u00e4bimiseks on soovitatav eelnevalt l\u00e4bi t\u00f6\u00f6tada Tarkvaraarenduse \u00f5piku 2. tr\u00fcki teema <a href=\"https:\/\/web.htk.tlu.ee\/digitaru\/tarkvara2\/chapter\/flask-sissejuhatus\/\">Veebirakenduse loomine. Flask<\/a>. Seda seet\u00f5ttu, et projekti peat\u00fckid on m\u00f5eldud seal \u00f5pitud Flaski teadmiste ning siin moodulis \u00f5pitud p\u00e4ringute teadmiste kinnistamiseks. Projekti peat\u00fckke saab l\u00e4bida ka ilma Flaski \u00f5ppematerjali uurimata, kuid sellisel juhul tuleb t\u00f5en\u00e4oliselt iseseisvalt ja jooksvalt lisainfot otsida.<\/p>\n<p>Oleme praeguseks omandanud piisavalt teadmisi andmebaaside ja neist p\u00e4rimise kohta. Seega, saame neid ka \u00fche elulise projekti \u2013 otsingumoori loomise \u2013 tarbeks rakendada.<\/p>\n<p>Loodav otsingumootori on m\u00f5eldud Netflixi andmebaasist teoste mugavaks otsimiseks. Projekt on sobiv on viis p\u00e4ringute reaalsete kasutusalade tutvustamiseks, kuna pea k\u00f5ik internetist leitavad otsingumootorid (sh igasugused v\u00e4iksed otsinguv\u00e4ljad) kasutavad tegelikkuses oma t\u00f6\u00f6ks andmebaasi p\u00e4ringuid.<\/p>\n<p>Kui me varasemates peat\u00fckkides kasutasime 5 faili jaotatud ning eelt\u00f6\u00f6deldud andmeid Netflixi teoste kohta, siis selle projekti raames kasutame lihtsuse nimel vaid algandmeid. Neid laeme alla aga hiljem.<\/p>\n<h2>Tarkvara installimine ja moodulite paigaldamine<\/h2>\n<p>Esmalt on soovitatav installida arenduskeskkond Thonny. Soovi korral leiab selleks juhendeid Programmeerimise \u00f5piku peat\u00fcki Sissejuhatus alampeat\u00fckist <a href=\"https:\/\/web.htk.tlu.ee\/digitaru\/programmeerimine\/chapter\/programm\/\">Programm<\/a>.<\/p>\n<p>P\u00e4rast Thonny installimist on tarvis paigaldada kaks moodulit \u2013 <em>Flask<\/em> ja <em>Flask-SQLAlchemy<\/em>.<\/p>\n<p><em>Flask<\/em>-i mooduli paigaldamiseks tuleb k\u00f5igepealt valida Thonny men\u00fc\u00fcst <em>Tools \u2192 Manage Packages<\/em>. Seej\u00e4rel tuleb otsinguaknasse kirjutada <em>Flask<\/em> ning klikata nupule <em>Search on PyPi<\/em>. P\u00e4rast seda tuleb vajutada valikule <em>Flask<\/em> ning seej\u00e4rel nupule <em>Install<\/em>.<\/p>\n<p>Mooduli <em>Flask-SQLAlchemy<\/em> installimine k\u00e4ib identselt.<\/p>\n<p>Mooduliga <em>Flask-SQLAlchemy<\/em> tuleb automaatselt kaasa ka moodul <em>SQLAlchemy<\/em>. K\u00e4esoleva \u00f5ppematerjali koostamise ajal oli selle v\u00e4rskeim (ametlikult) stabiilne versioon 1.4.1. Selle versiooniga esineb andmebaasiga \u00fchendust luues probleeme. Seega tuleb mooduli <em>SQLAlchemy<\/em> versiooni langetada.<\/p>\n<p>Mooduli versiooni langetamiseks tuleb <em>Manage Packages<\/em> vaatest esmalt moodul <em>SQLAlchemy<\/em> vasakult listist \u00fcles otsida ning seej\u00e4rel sellele klikata. Avanenud vaates tuleb vajutada nupule &#8216;<em>&#8230;&#8217;<\/em>, nii nagu alloleval pildil.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-737\" src=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/1.png\" alt=\"Mooduli versiooni langetamise esimene samm\" width=\"667\" height=\"458\" srcset=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/1.png 667w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/1-300x206.png 300w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/1-65x45.png 65w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/1-225x154.png 225w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/1-350x240.png 350w\" sizes=\"auto, (max-width: 667px) 100vw, 667px\" \/><\/p>\n<p>Seej\u00e4rel tuleb valida soovitud versioon, milleks on viimane kindlalt t\u00f6\u00f6tav versioon 1.3.23 ning l\u00f5puks tuleb klikata nupul <em>Install<\/em>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-738\" src=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/2-1.png\" alt=\"Mooduli versiooni langetamise teine samm\" width=\"185\" height=\"210\" srcset=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/2-1.png 185w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/2-1-65x74.png 65w\" sizes=\"auto, (max-width: 185px) 100vw, 185px\" \/><\/p>\n<p>P\u00e4rast seda avaneb laadimisribaga aken ning laadimise l\u00f5ppedes on mooduli versioon langetatud. V\u00f5imalik, et l\u00f5pus n\u00e4idatakse \u00f5igustega seotud veateadet, kuid see ei ole siinkohal \u00fcldjuhul t\u00e4henduslik ning versiooni langetamine peaks siiski t\u00f6\u00f6tama.<\/p>\n<p>N\u00fc\u00fcd ongi tarkvara edukalt installitud ning vajalikud moodulid paigaldatud.<\/p>\n<h2>Algse programmi loomine<\/h2>\n<p>Alustuseks tuleks meeldivasse asukohta luua kaust, kuhu hakkame omakorda projektiga seotud faile looma.<\/p>\n<p>Alustame sellega, et loome oma Flaski programmi aluse, mis renderdab aadressile <a href=\"http:\/\/127.0.0.1:5000\/teosed\">127.0.0.1:5000\/teosed<\/a> faili <code>teosed.html<\/code> sisu. Faili <code>teosed.html<\/code> veel ei eksisteeri, kuid ka selle loome peatselt.<\/p>\n<p>Paneme meie programmi alusfaili nimeks <code>app.py<\/code> ning olgu selle sisu j\u00e4rgnev:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">from flask import Flask, render_template\r\n\r\napp = Flask(__name__)\r\n\r\n@app.route('\/teosed')\r\ndef teosed():\r\n\u00a0\u00a0\u00a0 return render_template('teosed.html', teosed=[])\r\n\r\nif __name__ == \"__main__\":\r\n\u00a0\u00a0\u00a0 app.run()<\/pre>\n<p><code><\/code><\/p>\n<p>Selleks, et me loodud faili ka jooksutada saaks, tuleks n\u00fc\u00fcd luua fail <code>teosed.html<\/code> ning selle baasfail <code>baas.html<\/code>. Failid <code>teosed.html<\/code> ja <code>baas.html<\/code> tuleks paigutada projekti kausta alamkausta <code>templates<\/code>, mis tuleb samuti siinkohal luua.<\/p>\n<p>Projekti kaust peaks hetkeseisuga v\u00e4lja n\u00e4gema selline:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1163\" src=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust1.png\" alt=\"Projekti kausta \u00fclesehitus 1\" width=\"594\" height=\"65\" srcset=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust1.png 594w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust1-300x33.png 300w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust1-65x7.png 65w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust1-225x25.png 225w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust1-350x38.png 350w\" sizes=\"auto, (max-width: 594px) 100vw, 594px\" \/><\/p>\n<p>Loome esimesena faili baas.html, kuna fail teosed.html p\u00f5hineb osaliselt sellel. Olgu faili <code>baas.html<\/code> sisu j\u00e4rgnev:<\/p>\n<p><code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n    &lt;meta charset=\"UTF-8\"&gt;\r\n    {% block head %} &lt;title&gt;Otsingumootor&lt;\/title&gt; {% endblock %}\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n    {% block body %} {% endblock %}\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<p><code><\/code><\/p>\n<p>Loodud fail t\u00e4psustab hetkel peamiselt seda, et k\u00f5igi muude <code>.html<\/code> failide pealkiri olgu Otsingumootor juhul, kui seda pole neis failides \u00fcle kirjutatud.<\/p>\n<p>N\u00fc\u00fcd saame luua ka faili <code>teosed.html<\/code>, mille sisu olgu j\u00e4rgnev:<\/p>\n<p><code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">{% extends 'baas.html' %}\r\n{% block body %}\r\n&lt;h1&gt;Teosed&lt;\/h1&gt;\r\n&lt;table&gt;\r\n    &lt;tr&gt;\r\n        &lt;th&gt;Pealkiri&lt;\/th&gt;\r\n        &lt;th&gt;T\u00fc\u00fcp&lt;\/th&gt;\r\n        &lt;th&gt;Riigid&lt;\/th&gt;\r\n        &lt;th&gt;Aasta&lt;\/th&gt;\r\n        &lt;th&gt;\u017danrid&lt;\/th&gt;\r\n        &lt;th&gt;N\u00e4itlejad&lt;\/th&gt;\r\n        &lt;th&gt;Kirjeldus&lt;\/th&gt;\r\n    &lt;\/tr&gt;\r\n    {% for teos in teosed %}\r\n        &lt;tr&gt;\r\n            &lt;td&gt;{{ teos.pealkiri }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.tuup }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.riigid }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.valjalaske_aasta }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.zanrid }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.naitlejad }}&lt;\/td&gt;\r\n            &lt;td&gt;{{ teos.kirjeldus }}&lt;\/td&gt;\r\n        &lt;\/tr&gt;\r\n    {% endfor %}\r\n&lt;\/table&gt;\r\n{% endblock %}<\/pre>\n<p><code><\/code><\/p>\n<p>Failis <code>teosed.html<\/code> t\u00e4psustame esmalt seda, et viitame failile <code>baas.html<\/code>. Seej\u00e4rel alustame <code>body<\/code> plokiga, mille sisse loome teoste tabeli. Tabeli veergude pealkirjad m\u00e4\u00e4rame k\u00e4sitsi, kuid tabelis kuvatavad andmeread tulevad argumendist <code>teosed<\/code>. M\u00e4letatavasti andsime failis <code>app.py<\/code> failile <code>teosed.html<\/code> hetkel ette t\u00fchja listi, seega on tabel t\u00fchi.<\/p>\n<p>Projekti kausta alamkausta <code>templates<\/code> sisu peaks hetkeseisuga v\u00e4lja n\u00e4gema selline:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1164\" src=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust2.png\" alt=\"Projekti kausta templates \u00fclesehitus\" width=\"595\" height=\"64\" srcset=\"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust2.png 595w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust2-300x32.png 300w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust2-65x7.png 65w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust2-225x24.png 225w, https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-content\/uploads\/sites\/21\/2021\/03\/kaust2-350x38.png 350w\" sizes=\"auto, (max-width: 595px) 100vw, 595px\" \/><\/p>\n<p>Kui k\u00f5ik failid on loodud, v\u00f5ib jooksutada faili <code>app.py<\/code>. Seni valminud programmi tulemust saab brauseri abil vaadata aadressil <a href=\"http:\/\/127.0.0.1:5000\/teosed\">127.0.0.1:5000\/teosed<\/a> v\u00f5i <a href=\"5000\/teosed\">localhost:5000\/teosed<\/a>.<\/p>\n<h2>Andmebaasi ja selle tabeli loomine ning andmetega t\u00e4itmine<\/h2>\n<p>Selleks, et loodud tabelis andmeid kuvada saaks, tuleb luua andmebaas ning selle sisse Netflixi teoste andmeid hoiustav tabel. Esmalt tuleb hakata t\u00e4iendama faili <code>app.py<\/code>.<\/p>\n<p>Lisame importide hulka j\u00e4rgneva rea, mille abil impordime andmebaasiga suhtlemiseks kasutatava mooduli <em>SQLAlchemy<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">from flask_sqlalchemy import SQLAlchemy<\/pre>\n<p>Seej\u00e4rel tuleks p\u00e4rast rida\u00a0<code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">app = Flask(__name__)<\/code> lisada kolm andmebaasi loomise ja seadistamisega seotud koodirida:<\/p>\n<p><code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:\/\/\/teosed.db'\r\napp.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\r\ndb = SQLAlchemy(app)<\/pre>\n<p><code><\/code><\/p>\n<p>Esimese reaga m\u00e4\u00e4rame andmebaasi faili salvestamise asukoha. Kasutatud kirjapilt t\u00e4hendab seda, et fail <code>teosed.db<\/code> luuakse failiga <code>app.py<\/code> samasse kausta. Teise reaga m\u00e4\u00e4rame, et ei soovi muudatusi j\u00e4lgida ning kolmanda reaga loomegi andmebaasi.<\/p>\n<p>Esimeses reas v\u00f5is m\u00e4rgata s\u00f5na <em>sqlite<\/em>. See viitab sellele, et me kasutame andmebaasi juhtimiss\u00fcsteemina <em>SQLite<\/em>&#8217;i, mitte <em>PostgreSQL<\/em>&#8217;i, nagu oleme teinud siiani. <em>SQLite<\/em> on t\u00f5en\u00e4oliselt enim kasutatud andmebaasi juhtimiss\u00fcsteem maailmas, kuna see on mahult v\u00e4ike, lihtne ning v\u00e4ga paljudesse programmidesse sisse ehitatud. Seega sobib ta h\u00e4sti ka meie v\u00e4ikese projekti jaoks. Soovi korral v\u00f5ib <em>SQLite<\/em>&#8217;i kohta juurde lugeda selle <a href=\"https:\/\/www.sqlite.org\/index.html\">kodulehelt<\/a>.<\/p>\n<p>Kuna me kasutame andmebaasiga suhtlemiseks niikuinii moodulit <em>SQLAlchemy<\/em> ei m\u00f5juta meid eriti see, milline andmebaasi juhtimiss\u00fcsteem selle taga on. Seega v\u00f5iksime kasutada endiselt <em>PostgreSQL<\/em>&#8217;i, kuid see teeks seadistamise m\u00f5nev\u00f5rra keerukamaks.<\/p>\n<p>J\u00e4rgmise sammuna tuleks loodud andmebaasi luua tabel Teosed, milles hakkame hoiustama k\u00f5iki teostega seotud andmeid. Enne seda tuleks aga tutvuda meie algandmetega, mis on p\u00e4rit <a href=\"https:\/\/www.kaggle.com\/shivamb\/netflix-shows\">siit<\/a>. Varasemates peat\u00fckkides kasutasime t\u00f6\u00f6deldud versiooni samadest andmetest.<\/p>\n<p>N\u00fc\u00fcd tuleks andmed ka alla laadida. Seda v\u00f5ib teha ka andmete algallikast, kuid vigade v\u00e4ltimiseks on seda soovitatav teha <a href=\"https:\/\/drive.google.com\/file\/d\/15Dtbeo5VJIc0vRjSL07XuFGIM2UTG1Ew\/view?usp=sharing\">siit<\/a>. Andmetega t\u00f6\u00f6tame t\u00e4psemalt edasi p\u00e4rast tabeli loomist.<\/p>\n<p>Selleks, et tabel Teosed luua, t\u00e4iendame taaskord faili <code>app.py<\/code>. J\u00e4rgnevad read tuleks lisada faili p\u00e4rast andmebaasi loomise osa:<\/p>\n<p><code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">class Teosed(db.Model):\r\n    id = db.Column(db.String(10000), primary_key=True)\r\n    tuup = db.Column(db.String(7), nullable=False)\r\n    pealkiri = db.Column(db.String(150), nullable=False)\r\n    lavastajad = db.Column(db.Text)\r\n    naitlejad = db.Column(db.Text)\r\n    riigid = db.Column(db.Text)\r\n    lisamise_kuupaev = db.Column(db.String(100))\r\n    valjalaske_aasta = db.Column(db.Integer, nullable=False)\r\n    vanusepiirang = db.Column(db.String(20))\r\n    kestus = db.Column(db.String(20), nullable=False)\r\n    zanrid = db.Column(db.Text, nullable=False)\r\n    kirjeldus = db.Column(db.String(500), nullable=False)\r\n    def __repr__(self):\r\n        return 'Teos: ' + str(self.pealkiri)<\/pre>\n<p><code><\/code><\/p>\n<p>Esimese reaga t\u00e4psustame tabeli nime ning selle, millise andmebaasiga see seotud on.<\/p>\n<p>J\u00e4rgmised 12 rida t\u00e4histavad tabeli veerge ehk tunnuseid. Nagu n\u00e4ha, siis tuleb primaarv\u00f5tme t\u00e4psustamiseks kirjutada <code>primary_key=True<\/code> ning selleks, et mitte lubada v\u00e4\u00e4rtusi <code><span style=\"color: #000080\"><strong><span style=\"color: #970000\">NULL<\/span><\/strong><\/span><\/code>, tuleb kirjutada <code>nullable=False<\/code>.<\/p>\n<p>Andmet\u00fc\u00fcpidena kasutame siinkohal <code>String<\/code>&#8217;i, <code>Text<\/code>&#8217;i ja <code>Integer'<\/code>i. Seega erinevad need m\u00f5nev\u00f5rra seni kasutatust. Kui me <em>PostgreSQL<\/em>&#8216;s kasutasime s\u00f5ne t\u00fc\u00fcpi v\u00e4\u00e4rtuste jaoks andmet\u00fc\u00fcpi <code><span style=\"color: #000080\"><strong>VARCHAR<\/strong><\/span><\/code>, siis n\u00fc\u00fcd tuleb kasutada andmet\u00fc\u00fcpi <code>String<\/code>. Pikkuse t\u00e4psustamine k\u00e4ib aga identselt. Andmet\u00fc\u00fcp <code>Text<\/code> t\u00e4histab teadmata pikkusega s\u00f5nesid ning <code>Integer<\/code> t\u00e4histab t\u00e4isarve, nagu ikka.<\/p>\n<p>Viimase kahe koodireaga t\u00e4psustame seda, kuidas k\u00e4surealt selle tabeli andmeid p\u00e4rides igat andmerida p\u00e4ringu tulemuses kujutatakse. Kasutatud kirjapilt t\u00e4hendab seda, et pika andmerea asemel kuvatakse lihtsalt n\u00e4iteks &#8216;Teosed: The Queen&#8217;s Gambit&#8217;.<\/p>\n<p>N\u00fc\u00fcd on meil v\u00f5imalik andmebaas ning selle sees olev tabel Teosed p\u00e4riselt mingisse faili luua. Selleks kasutame Thonny k\u00e4surida. Kui k\u00e4surida pole juba n\u00e4htaval, vali \u00fclevalt men\u00fc\u00fcst <em>View<\/em> <em>\u2192 <\/em><em>Shell<\/em>, p\u00e4rast mida peaks k\u00e4surida koodivaate all avanema.<\/p>\n<p>K\u00e4ivita fail <code>app.py<\/code>, kui sa pole seda juba teinud. Soovi korral uuri veebilehte <a href=\"http:\/\/127.0.0.1:5000\/teosed\">127.0.0.1:5000\/teosed<\/a> ning seej\u00e4rel peata fail.<\/p>\n<p>Andmebaasi ja tabeli loomiseks kirjuta k\u00e4suritta j\u00e4rjest (kuid v\u00e4ikese vahega) j\u00e4rgnevad k\u00e4sud:<\/p>\n<ol>\n<li><code><code><code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">from app import db<\/code><\/code><\/code><code><code><\/code><\/code><\/li>\n<li><code><code><code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">db.create_all()<\/code><\/code><\/code><code><\/code><\/li>\n<\/ol>\n<p>N\u00fc\u00fcd saame kontrollida, kas projekti kausta tekkis andmebaasi fail <code>teosed.db<\/code>. Kui jah, on k\u00f5ik h\u00e4sti. Kui ei, vaata hoolikalt \u00fcle senised sammud ja proovi need uuesti l\u00e4bi teha.<\/p>\n<p>Kuna andmebaas ja teoste tabel on n\u00fc\u00fcd loodud, saame andmeid tabelisse lisama hakata. Kui andmed pole juba alla laetud, tuleks seda n\u00fc\u00fcd teha. Seej\u00e4rel tuleb allalaetud kokkupakitud andmed lahti pakkida ning projekti kausta t\u00f5sta. L\u00f5puks tuleb luua ka uus koodifail <code>abi.py<\/code>. Nii andmefail kui ka koodifail peaksid paiknema samal tasandil mis <code>app.py<\/code>.<\/p>\n<p>Faili <code>abi.py<\/code> paneme koodi, mille abil lisatakse failis <code>netflix_titles.csv<\/code> olevad andmed andmebaasi faili <code>teosed.db<\/code>.<\/p>\n<p>Olgu faili <code>abi.py<\/code> sisu j\u00e4rgnev:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">import csv, sqlite3\r\n\r\ncon = sqlite3.connect(\"C:\/Users\/Kasutaja\/Desktop\/L\u00f5put\u00f6\u00f6\/Otsingumootor_jooksev\/teosed.db\")\r\ncur = con.cursor()\r\n\r\nwith open('netflix_titles.csv','r', encoding='utf8') as f:\r\n    dr = csv.DictReader(f)\r\n    andmeread = [(i['show_id'], i['type'], i['title'], i['director'], i['cast'], i['country'], i['date_added'],\r\n    i['release_year'], i['rating'], i['duration'], i['listed_in'], i['description'])\r\n    for i in dr]\r\n\r\ncur.executemany(\"INSERT INTO Teosed (id, tuup, pealkiri, lavastajad, naitlejad, riigid, lisamise_kuupaev, valjalaske_aasta, vanusepiirang, kestus, zanrid, kirjeldus) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);\",\r\nandmeread)\r\ncon.commit()\r\ncon.close()<\/pre>\n<p><strong>Muuda<\/strong> enne j\u00e4tkamist koodireas\u00a0<code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">con = sqlite3.connect(\"C:\/Users\/Kasutaja\/Desktop\/L\u00f5put\u00f6\u00f6\/Otsingumootor_jooksev\/teosed.db\")<\/code><br \/>\nn\u00e4idatud failitee enda projektile vastavaks!<\/p>\n<p>Kuna tegemist on vaid abifailiga, ei keskendu me siinkohal selle t\u00f6\u00f6p\u00f5him\u00f5tetele. Soovi korral saab aga <a href=\"https:\/\/docs.python.org\/3\/library\/sqlite3.html\"><em>sqlite3<\/em> dokumentatsioonist<\/a> uurida n\u00e4iteks seda, mida t\u00e4hendavad koodis kasutatud <em>Connection<\/em> ja <em>Cursor<\/em>.<\/p>\n<p><strong>Jooksuta<\/strong> n\u00fc\u00fcd faili <code>abi.py<\/code>, mille tulemusena lisatakse k\u00f5ik <code>.csv<\/code> failis olevad andmed meie andmebaasi!<\/p>\n<p>Viimaks, et meie andmebaasis olevaid andmeid ka aadressil <a href=\"http:\/\/127.0.0.1:5000\/teosed\">127.0.0.1:5000\/teosed<\/a> kuvataks, tuleb faili <code>app.py<\/code> meetodit <code>teosed()<\/code> veidi kohandada. Muuda see j\u00e4rgnevaks:<code><\/code><code><\/code><br \/>\n<code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">@app.route('\/teosed')\r\ndef teosed():\r\n    koik_teosed = Teosed.query.all()\r\n    return render_template('teosed.html', teosed=koik_teosed)<\/pre>\n<p><code><\/code><\/p>\n<p><code><\/code><\/p>\n<p>Selle tulemusena p\u00e4ritakse muutujasse <code>koik_teosed<\/code> tabeli Teosed kogu sisu. Muutja <code>koik_teosed<\/code> v\u00e4\u00e4rtuse anname omakorda edasi failile <code>teosed.html<\/code>. M\u00e4letatavasti kasutati failis <code>teosed.html<\/code> argumendi teosed v\u00e4\u00e4rtust tabeli andmetega t\u00e4itmiseks.<\/p>\n<p>Jooksuta n\u00fc\u00fcd uuesti faili <code>app.py<\/code> ning peaksid aadressil <a href=\"http:\/\/127.0.0.1:5000\/teosed\">127.0.0.1:5000\/teosed<\/a> n\u00e4gema k\u00f5igi teoste andmeid. Kuigi andmebaasi tabelis oli veerge 12, on veebilehel neid k\u00f5igest 7. See on nii, kuna me t\u00e4psustasime failis <code>teosed.html<\/code> vaid 7 veeru nimed, mille v\u00e4\u00e4rtuseid me n\u00e4ha soovime.<\/p>\n<p>J\u00e4rgmises peat\u00fckis kujundame oma projekti v\u00e4limust ning lisame erinevaid otsingufunktsionaalsusi.<\/p>\n","protected":false},"author":32,"menu_order":9,"template":"","meta":{"pb_show_title":"on","pb_short_title":"","pb_subtitle":"","pb_authors":[],"pb_section_license":""},"chapter-type":[],"contributor":[],"license":[],"class_list":["post-244","chapter","type-chapter","status-publish","hentry"],"part":31,"_links":{"self":[{"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/pressbooks\/v2\/chapters\/244","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/pressbooks\/v2\/chapters"}],"about":[{"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/wp\/v2\/types\/chapter"}],"author":[{"embeddable":true,"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/wp\/v2\/users\/32"}],"version-history":[{"count":91,"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/pressbooks\/v2\/chapters\/244\/revisions"}],"predecessor-version":[{"id":1371,"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/pressbooks\/v2\/chapters\/244\/revisions\/1371"}],"part":[{"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/pressbooks\/v2\/parts\/31"}],"metadata":[{"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/pressbooks\/v2\/chapters\/244\/metadata\/"}],"wp:attachment":[{"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/wp\/v2\/media?parent=244"}],"wp:term":[{"taxonomy":"chapter-type","embeddable":true,"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/pressbooks\/v2\/chapter-type?post=244"},{"taxonomy":"contributor","embeddable":true,"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/wp\/v2\/contributor?post=244"},{"taxonomy":"license","embeddable":true,"href":"https:\/\/web.htk.tlu.ee\/digitaru\/lisamoodulid\/wp-json\/wp\/v2\/license?post=244"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}