›_ebskola.lv
Prog I · 12. tēma · 6 stundas - Flask · PostgreSQL · Deploy

Pilnvērtīga //
izstrāde un deploy

Apvieno visu kursu: Flask + PostgreSQL + mākonis. Kursa beigās: publicēta web lietotne internetā.

6 stundas Flask · SQLAlchemy Daudzspēlētāju Krustiņi
# 01 stundu plāns

6 stundas - full-stack un publicēšana

noslēguma projekts →
PārlūksHTML/JSFlaskPython APIroutesDBPostgresFront-end ↔ Back-end ↔ Datubāze// full-stack
arhitektūrafull-stack

Front-end un back-end arhitektūra

Klienta-servera modelis, HTTP pieprasījumi, REST API dizains, koda organizācija slāņos.

12.1 stundaatvērt ↗
@app.route('/')def index(): return render_template()@app.route('/api/gājiens', methods=['POST'])def gājiens(): return jsonify(rezultāts)@app.route('/spēlētāji')def spēlētāji(): return get_all()// Flask routes
Flask · Blueprintsbackend

Flask kā web serveris

Maršrutu organizēšana ar Blueprints, request/response, Flask-SQLAlchemy integrācija.

12.2 stundaatvērt ↗
GET/api/spēles200 OKPOST/api/spēles201 CreatedPUT/api/spēles/42200 OKDELETE/api/spēles/42204// REST API
REST · JSONAPI

REST API izstrāde

RESTful endpoint dizains, HTTP statusa kodi, jsonify(), CORS.

12.3 stundaatvērt ↗
Browser (JS)const r = await fetch( '/api/gajiens', {method:'POST', ...})Flask (Python)@app.route('/api/...')def gajiens(): return jsonify(res)// fetch + Flask
JS · Flaskintegrācija

Front-end + API integrācija

JS fetch() → Flask POST → DB → JSON atbilde → DOM atjaunošana.

12.4 stundaatvērt ↗
Lokāligit pushGitHub CIRenderhttps://... 🔒ENV vars · SECRET_KEY · DATABASE_URL// deploy
Render · deployizvietošana

Izvietošana mākonī un drošība

Render vai Railway deploy, environment variables, HTTPS, requirements.txt.

12.5 stundaatvērt ↗
krustinji.onrender.com 🔒XOXOXFlask · PostgreSQL · publicēts!// kursa noslēgums
Python · Full-stackprojekts

Noslēguma projekts: Daudzspēlētāju Krustiņi

Flask + PostgreSQL + JS - pilna publicēta web lietotne. Kursa noslēgums un portfolio gabals.

12.6 noslēguma projektsatvērt ↗
# 02 špikeris

12. tēmas špikeris - tīmekļa izstrāde

Klients-serveris, Flask, REST API, fetch un izvietošana. Katrs bloks atbilst vienai stundai.

12.1 Klients un serveris

  PĀRLŪKS (frontend)                    SERVERIS (backend)
  HTML / CSS / JavaScript               Python / Flask
  lietotāja datorā                      tavā vai mākoņa datorā
         │                                      │
         │──── GET /api/rezultati ─────────────►│
         │                                      │  lasa datubāzi
         │◄─── 200 OK + JSON ───────────────────│
         │                                      │
         │──── POST /api/rezultati + JSON ─────►│  pārbauda un saglabā
         │◄─── 201 Created ─────────────────────│

Statusa kodi:
  200 OK          viss kārtībā
  201 Created     jauns ieraksts izveidots
  400 Bad Request lietotājs atsūtīja sliktus datus
  404 Not Found   nav tādas adreses
  500 Server Error servera kods avarēja

GALVENAIS LIKUMS: serveris NEKAD neuzticas pārlūka datiem.
Uzvaras pārbaude, cena, tiesības - viss serverī, jo pārlūku var apiet.

Pārlūkā drīkst pārbaudīt ērtībai, bet serverī pārbaudīt ir obligāti.

12.2 Flask serveris

from flask import Flask, jsonify, request

app = Flask(__name__)
SPELETAJI = []

@app.route("/")
def home():
    return "<h1>Sveiks!</h1>"

@app.route("/api/speletaji")                 # GET pēc noklusējuma
def visi():
    return jsonify(SPELETAJI)                # bez jsonify nav JSON

@app.route("/api/speletaji", methods=["POST"])
def pievienot():
    dati = request.json
    SPELETAJI.append(dati)
    return jsonify(dati), 201                # 201 = izveidots

@app.route("/api/speletaji/<int:id>")
def viens(id):
    for s in SPELETAJI:
        if s["id"] == id: return jsonify(s)
    return jsonify({"kluda": "nav atrasts"}), 404

app.run(debug=True)     # debug=True TIKAI izstrādē!

Sarakstā glabātie dati pazūd, restartējot serveri - pastāvīgai glabāšanai vajag failu vai datubāzi.

12.3 REST API ar validāciju

@app.route("/api/rezultati", methods=["GET"])
def saraksts():
    limit = request.args.get("limit", 100, type=int)   # ?limit=5
    sakartoti = sorted(REZULTATI, key=lambda r: r["punkti"], reverse=True)
    return jsonify(sakartoti[:limit])

@app.route("/api/rezultati", methods=["POST"])
def pievienot():
    dati = request.json

    if not dati or "vards" not in dati:
        return jsonify({"kluda": "Trūkst lauks 'vards'"}), 400
    if not isinstance(dati.get("punkti"), int) or dati["punkti"] < 0:
        return jsonify({"kluda": "'punkti' jābūt pozitīvam skaitlim"}), 400

    dati["id"] = len(REZULTATI) + 1
    REZULTATI.append(dati)
    return jsonify(dati), 201

# REST likumi: viena adrese = viens resurss
#   GET    /api/rezultati       saraksts
#   POST   /api/rezultati       izveido jaunu
#   DELETE /api/rezultati/5     dzēš vienu

type=int pasargā no ?limit=abc - bez tā serveris atgrieztu 500.

12.4 fetch() - pārlūks runā ar serveri

async function ielade() {
  const r = await fetch("http://localhost:5000/api/rezultati");
  if (!r.ok) {                          // vienmēr pārbaudi
    console.error("Kļūda:", r.status);
    return;
  }
  const dati = await r.json();

  let html = "";
  for (const x of dati) {
    html += `<tr><td>${x.vards}</td><td>${x.punkti}</td></tr>`;
  }
  document.getElementById("saraksts").innerHTML = html;
}

document.getElementById("forma").addEventListener("submit", async (e) => {
  e.preventDefault();                   // BEZ ŠĪ lapa pārlādējas!
  await fetch("http://localhost:5000/api/rezultati", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ vards: vards.value, punkti: +punkti.value })
  });
  ielade();                             // atjauno tabulu
});

CORS kļūda konsolē? Serverī: pip install flask-cors un CORS(app).

12.5 Izvietošana un drošība

import os
from flask import Flask

app = Flask(__name__)

# NEKAD neraksti paroli kodā - lasi no vides mainīgā
DATABASE_URL = os.environ.get("DATABASE_URL")
SECRET_KEY = os.environ.get("SECRET_KEY", "dev-only-key")

# .env fails (LOKĀLI, .gitignore sarakstā):
#   DATABASE_URL=postgres://...
#   SECRET_KEY=...

# Pirms izvietošanas:
#   app.run(debug=False)        debug=True publiski rāda tavu kodu!
#   pip install gunicorn
#   pip freeze > requirements.txt
#   Procfile:  web: gunicorn app:app
#   .gitignore satur .env un venv/

# Render / Railway: pieslēdz GitHub krātuvi, vides mainīgos ievadi
# mājaslapas Environment sadaļā, nevis failā.

Parole, kas vienreiz nonākusi GitHub, ir uzskatāma par nopludinātu - to jāmaina, ne tikai jāizdzēš.

$ git push render main # kods → mākonis → pieejams visai pasaulei