Oppsett av et Joke API

Skip to content

Vi har allerede sett litt på Flask, men, som en repitisjon: hva er egentlig Flask? Det er en web-server. Altså, en bruker kan spørre om informasjon fra serveren, også får brukeren et svar tilbake. Men hva er dette egentlig i praksis?

Hva er et API?

Et API (Application Programming Interface) er en måte for programmer å kommunisere mellom hverandre. Et program kan spørre om informasjon fra et annet program, også får programmet et svar tilbake.

Var nå ikke dette ganske likt som Web-Serveren vi så i Flask? Det er det! Det vi lagde i Flask kan vi faktisk kalle et API.

I dette prosjektet skal vi ha denne filstrukturen:

Filstruktur

📁Flask_API
    📁static
    📁templates
        📄index.html
    🐍app.py
    📄jokes.json
    📄requirements.txt
Startkode (Click to expand)

Denne koden kan dere hente fra GitHub repoet. Eventuelt kan du sette opp prosjektet selv og “copy/paste” koden.

requirements.txt
flask
requests
jokes.json
{
   "jokes": [
        {
            "value": "Why did the chicken cross the road? Buck if i know!"
        },
        {
            "value": "Two tomatoes crossed the road, then one of them said, come on, ketchup!"
        }
    ]
}
app.py
from flask import Flask, jsonify, request, render_template
import json
import requests
import random

app = Flask(__name__)

JOKE_FILE = "jokes.json"

@app.route("/")
def index():
    return render_template("index.html", joke="")

if __name__ == '__main__':
    app.run(debug=True)
index.html
<h1>Joke API!</h1>

<form method="GET" action="/get-joke">
    <textarea id="the_joke" name="the_joke" rows="10" cols="50" readonly>{{ joke.value }}</textarea><br>
    <input type="submit" value="Get Joke">
</form>

<form method="POST" action="/add-joke">
    <label for="joke_text">Joke:</label><br>
    <textarea id="joke_text" name="joke_text" rows="10" cols="50" required></textarea><br>
    <input type="submit" value="Add Joke">
</form>

Kort forklart

  • app.py
    • Hovedprogrammet er her.
  • requirements.txt
    • Denne filen inneholder navnet på alle pakker som må til for at programmet skal kjøre.
    • Bruk gjerne disse når dere skal jobbe sammen på større prosjekter, det kan bli mange pakker etterhvert!
  • jokes.json
    • Denne filen skal holde på informasjonen om vitsene.
  • index.html
    • En template fil for å vise siden

Del 1 - Oppsett av programmet

Programmet krever noen pakker for å kjøre. Vi kunne ha installert alle manuelt, men de aller fleste større python prosjekter du kommer til å se, vil komme med en requirements.txt fil. Denne filen inneholder alt et program trenger for å kjøre.

Easy Oppgave 1.1a - Installere pakker

Åpne en terminalen og skriv kommandoen:
pip install -r .\requirements.txt

Dette vil automagisk (🧙‍♂️) installere alle pakkene som er nevnt der.

Easy Oppgave 1.1b - Teste koden

Kjør python filen app.py for å se om du har installert pakkene riktig.

Hva gjør koden?
# importer ting vi trenger
from flask import Flask, jsonify, request, render_template
import json
import requests
import random

# lag en server
app = Flask(__name__)

# fil som holder styr på vitsene
JOKE_FILE = "jokes.json"

@app.route("/")
def index():
    # her skal en 'render_template' sende en 'joke' tilbake til brukeren
    return render_template("index.html", joke="")

# kjører serveren i debug mode
if __name__ == '__main__':
    app.run(debug=True)

Medium Oppgave 1.2a - Not joking around

Legg til funksjonalitet for å hente ut en tilfeldig vits fra .json filen. Lag en route som heter /get-joke. Les om JSON i Python her: w3schools JSON.

Her må du også se litt på hvordan du kan lese en fil i Python, her er en måte du kan se på dette på: GeeksForGeeks read file.

Løsning
@app.route("/get-joke", methods=["GET"])
def joke():
    with open(JOKE_FILE, "r") as f:
        jokes = json.loads(f.read())

    joke = random.choice(jokes["jokes"])

    return render_template("index.html", joke=joke)
Bonusspørsmål (bare tenk)
  • Hva skjer nå hvis du trykker på “Get Joke” knappen?
  • Hva gjør linja med random.choice?
  • Hvorfor er det lurt å bruke ["jokes"] på slutten av linja?

Easy Oppgave 1.2b - Flere vitser

Legg til noen flere vitser i jokes.json manuelt, kjør koden på nytt, og se hva som skjer.

Hva gjør koden i index.html?

Koden er for det meste helt vanlig HTML-kode. Men det er noen tags (det mellom < og >) som du kanskje ikke har sett før.

Her brukes en form. En form er egentlig bare noe en bruker kan påvirke, kontrollere. Vi ser at det er to tags inni form. textarea er et område med tekst som en bruker kan skrive i. I denne står det readonly i, noe som betyr at den ikke kan skrives til av en bruker, men en nettside kan allikevel skrive noe til den, som er det vi gjør med render_template i python.

Du legger kanskje merke til at i denne form-en står det {{ joke.value }}. Dette er ikke HTML, men noe som kalles Jinja. Det er det som kalles et “templating language”. Altså, et “oppskrifts-språk”. Det gir altså en oppskrift på hvordan en nettside kan bygges opp.

Del 2 - Bruke et eksternt API i Flask

Siden et API er en måte for programmer å kommunisere mellom hverandre kan vi skrive kode i et program som henter informasjon fra et annet. Dette er ett av hovedbruksområdene til API-er.

Her skal vi se på et enkelt API for å hente Chuck Norris vitser.

Her står det litt informasjon om hvordan vi kan bruke API-et:

GET https://api.chucknorris.io/jokes/random

Dette betyr at vi må bruke en GET request med den gitte URL-en for å hente informasjonen. Du la kanskje merke til at det står methods=["GET"] i routen fra Oppgave 1.3. Dette betyr at vi skal hente informasjon. Dersom du skal sende informasjon, må du bruke en request-metode som heter POST. Men vi skal bare se på GET akkurat nå.

Medium Oppgave 2.1 - Chuckity Chuck

Lag en ny route som heter chuck og deretter ta i bruk requests pakken for å hente ut en respons. Lagre responsverdien i en variabel du kaller response.

Du kan lese om hvordan du kan bruke denne pakken her: Requests Quickstart

Det vi får tilbake i response variabelen er tekst (selv om det ser ut som json), så vi må gjøre teksten om til json ved å skrive joke = response.json().

Til slutt kan du returnere en render_template med vitsen. (Likt som i @app.route("/"))!

Løsningen
@app.route("/chuck", methods=["GET"])
def chuck():
    response = requests.get("https://api.chucknorris.io/jokes/random")
    joke = response.json()

    return render_template("index.html", joke=joke)

Easy Oppgave 2.2 - Kjør på!

Bruk http://127.0.0.1:5000/chuck i nettleseren nå, hva skjer?