Tilbake
4.4
Bygge eget API med Flask

4.4 Bygge eget API med Flask

Opprette REST API-endepunkter med Flask.

65 min
6 oppgaver
FlaskRutingEndepunkterREST
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 6 oppgaver

Så langt har vi brukt API-er laget av andre. Nå skal vi lære å bygge våre egne API-er med Flask, et enkelt og populært Python-rammeverk for webutvikling.

Med Flask kan vi:
- Lage REST API-er
- Definere endepunkter (ruter)
- Håndtere HTTP-forespørsler (GET, POST, PUT, DELETE)
- Returnere JSON-data
- Bygge backends for webapplikasjoner

I dette kapittelet skal vi lage et enkelt API fra bunnen av.

Flask er ikke inkludert i standard Python, så vi må installere det først:

pip install flask

Verifiser installasjonen:

import flask
print(flask.__version__)

Flask er et mikroframework, som betyr at det er minimalistisk og lett å komme i gang med. Det har ikke masse innebygde funksjoner, men kan utvides med plugins etter behov.

✏️Eksempel: Din første Flask-app

La oss lage en enkel Flask-applikasjon:

from flask import Flask

# Opprett Flask-app
app = Flask(__name__)

# Definer en rute (endepunkt)
@app.route('/')
def hjem():
    return 'Velkommen til mitt API!'

@app.route('/hei/<navn>')
def hei(navn):
    return f'Hei, {navn}!'

# Kjør serveren
if __name__ == '__main__':
    app.run(debug=True, port=5000)

Kjør programmet:

python app.py

Test i nettleseren:
- http://localhost:5000/ → "Velkommen til mitt API!"
- http://localhost:5000/hei/Emma → "Hei, Emma!"

Forklaring:
- @app.route() er en decorator som definerer en URL-rute
- Funksjonen under returnerer hva som skal vises
- <navn> er en URL-parameter
- debug=True gir bedre feilmeldinger og automatisk restart

Flask-ruter og HTTP-metoder

En rute (route) er en URL-sti som Flask lytter på. Når noen sender en forespørsel til den ruten, kjører Flask den tilknyttede funksjonen.

HTTP-metoder:
Du kan spesifisere hvilke HTTP-metoder en rute skal akseptere:

@app.route('/data', methods=['GET'])
def hent_data():
    return 'GET-forespørsel'

@app.route('/data', methods=['POST'])
def opprett_data():
    return 'POST-forespørsel'

Standardmetoden er GET hvis ikke annet er spesifisert.

✏️Eksempel: Returnere JSON

For å lage et ordentlig API må vi returnere JSON i stedet for tekst:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/api/info')
def info():
    data = {
        'navn': 'Mitt API',
        'versjon': '1.0',
        'forfatter': 'Emma Hansen'
    }
    return jsonify(data)

@app.route('/api/elever')
def elever():
    elever = [
        {'id': 1, 'navn': 'Emma', 'alder': 18},
        {'id': 2, 'navn': 'Lars', 'alder': 17},
        {'id': 3, 'navn': 'Sara', 'alder': 16}
    ]
    return jsonify(elever)

if __name__ == '__main__':
    app.run(debug=True)

Test:

curl http://localhost:5000/api/info
curl http://localhost:5000/api/elever

Svar:

{
  "navn": "Mitt API",
  "versjon": "1.0",
  "forfatter": "Emma Hansen"
}

jsonify() konverterer automatisk Python-objekter til JSON-respons.

Flask lar deg hente query-parametre fra URL-en:

URL-eksempel:

http://localhost:5000/sok?q=python&limit=10

Hente parametre:

from flask import request

@app.route('/sok')
def sok():
    q = request.args.get('q', '')  # Default: tom string
    limit = request.args.get('limit', 10, type=int)

    return jsonify({
        'sokord': q,
        'limit': limit
    })

Test:

GET /sok?q=flask&limit=5

Svar:

{
  "sokord": "flask",
  "limit": 5
}

✏️Eksempel: POST-forespørsler

For å motta data fra klienten bruker vi POST:

from flask import Flask, request, jsonify

app = Flask(__name__)

# Midlertidig database (liste)
elever = []
neste_id = 1

@app.route('/api/elever', methods=['GET'])
def hent_elever():
    return jsonify(elever)

@app.route('/api/elever', methods=['POST'])
def legg_til_elev():
    global neste_id

    # Hent JSON-data fra forespørselen
    data = request.get_json()

    # Valider data
    if not data or 'navn' not in data:
        return jsonify({'error': 'Navn mangler'}), 400

    # Opprett ny elev
    ny_elev = {
        'id': neste_id,
        'navn': data['navn'],
        'alder': data.get('alder', 0)
    }

    elever.append(ny_elev)
    neste_id += 1

    return jsonify(ny_elev), 201  # 201 Created

if __name__ == '__main__':
    app.run(debug=True)

Test med curl:

curl -X POST http://localhost:5000/api/elever \
  -H "Content-Type: application/json" \
  -d '{"navn": "Emma", "alder": 18}'

Svar:

{
  "id": 1,
  "navn": "Emma",
  "alder": 18
}

✏️Eksempel: Komplett CRUD API

Her er et fullstendig API med alle CRUD-operasjoner:

from flask import Flask, request, jsonify

app = Flask(__name__)

bøker = [
    {'id': 1, 'tittel': '1984', 'forfatter': 'George Orwell'},
    {'id': 2, 'tittel': 'Doppler', 'forfatter': 'Erlend Loe'}
]
neste_id = 3

# CREATE
@app.route('/api/boker', methods=['POST'])
def opprett_bok():
    global neste_id
    data = request.get_json()

    if not data or 'tittel' not in data:
        return jsonify({'error': 'Tittel mangler'}), 400

    ny_bok = {
        'id': neste_id,
        'tittel': data['tittel'],
        'forfatter': data.get('forfatter', 'Ukjent')
    }
    bøker.append(ny_bok)
    neste_id += 1

    return jsonify(ny_bok), 201

# READ (alle)
@app.route('/api/boker', methods=['GET'])
def hent_alle_boker():
    return jsonify(bøker)

# READ (én)
@app.route('/api/boker/<int:bok_id>', methods=['GET'])
def hent_bok(bok_id):
    bok = next((b for b in bøker if b['id'] == bok_id), None)
    if bok:
        return jsonify(bok)
    return jsonify({'error': 'Bok ikke funnet'}), 404

# UPDATE
@app.route('/api/boker/<int:bok_id>', methods=['PUT'])
def oppdater_bok(bok_id):
    bok = next((b for b in bøker if b['id'] == bok_id), None)
    if not bok:
        return jsonify({'error': 'Bok ikke funnet'}), 404

    data = request.get_json()
    bok['tittel'] = data.get('tittel', bok['tittel'])
    bok['forfatter'] = data.get('forfatter', bok['forfatter'])

    return jsonify(bok)

# DELETE
@app.route('/api/boker/<int:bok_id>', methods=['DELETE'])
def slett_bok(bok_id):
    global bøker
    bok = next((b for b in bøker if b['id'] == bok_id), None)
    if not bok:
        return jsonify({'error': 'Bok ikke funnet'}), 404

    bøker = [b for b in bøker if b['id'] != bok_id]
    return jsonify({'message': 'Bok slettet'})

if __name__ == '__main__':
    app.run(debug=True)

Dette er et komplett REST API med alle grunnleggende operasjoner.

Du kan teste ditt eget Flask-API med requests-biblioteket:

import requests

# GET alle bøker
response = requests.get('http://localhost:5000/api/boker')
print(response.json())

# POST ny bok
ny_bok = {'tittel': 'Sofies verden', 'forfatter': 'Jostein Gaarder'}
response = requests.post('http://localhost:5000/api/boker', json=ny_bok)
print(response.json())

# PUT (oppdater)
oppdatering = {'tittel': 'Sofies verden (revidert)'}
response = requests.put('http://localhost:5000/api/boker/3', json=oppdatering)
print(response.json())

# DELETE
response = requests.delete('http://localhost:5000/api/boker/3')
print(response.json())

Dette lar deg automatisere testing av API-et ditt.

✏️Praktisk eksempel: Værlogg-API

La oss lage et API for å logge værobservasjoner:

from flask import Flask, request, jsonify
from datetime import datetime

app = Flask(__name__)

observasjoner = []
neste_id = 1

@app.route('/api/vaer', methods=['POST'])
def legg_til_observasjon():
    """Registrer ny værobservasjon"""
    global neste_id
    data = request.get_json()

    if not data or 'temperatur' not in data:
        return jsonify({'error': 'Temperatur mangler'}), 400

    observasjon = {
        'id': neste_id,
        'temperatur': data['temperatur'],
        'luftfuktighet': data.get('luftfuktighet'),
        'vindhastighet': data.get('vindhastighet'),
        'tidspunkt': datetime.now().isoformat()
    }

    observasjoner.append(observasjon)
    neste_id += 1

    return jsonify(observasjon), 201

@app.route('/api/vaer', methods=['GET'])
def hent_observasjoner():
    """Hent alle observasjoner, eventuelt filtrert"""
    limit = request.args.get('limit', len(observasjoner), type=int)
    return jsonify(observasjoner[-limit:])

@app.route('/api/vaer/statistikk', methods=['GET'])
def statistikk():
    """Beregn statistikk over observasjoner"""
    if not observasjoner:
        return jsonify({'error': 'Ingen data'}), 404

    temperaturer = [o['temperatur'] for o in observasjoner]

    stats = {
        'antall': len(observasjoner),
        'gjennomsnitt': sum(temperaturer) / len(temperaturer),
        'min': min(temperaturer),
        'max': max(temperaturer)
    }

    return jsonify(stats)

if __name__ == '__main__':
    app.run(debug=True)

Bruk:

# Legg til observasjon
curl -X POST http://localhost:5000/api/vaer \
  -H "Content-Type: application/json" \
  -d '{"temperatur": 15.5, "luftfuktighet": 65}'

# Hent statistikk
curl http://localhost:5000/api/vaer/statistikk

Dette viser hvordan du kan bygge et praktisk API for datainnsamling.

Oppsummering

I dette kapittelet har du lært:

- Flask: rammeverk for å bygge web-applikasjoner og API-er.
- Ruter: URL-stier Flask lytter på.
- HTTP-metoder: GET, POST, PUT og DELETE i ruter.
- Returnere JSON: levere data fra eget API.
- CRUD-API: opprette, lese, oppdatere og slette ressurser.

Noekkelbegreper


BegrepForklaring
FlaskPython-rammeverk for web og API-er
RuteURL-sti som Flask reagerer på
CRUDCreate, Read, Update, Delete

Oppgaver

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.