Von Steven Jacon

Das World Wide Web ist ein großartiger Ort, an dem man jegliche Information finden kann, wenn man nur möchte. Doch was ist, wenn man selbst Informationen zur Verfügung stellen will? Als Entwickler wird man durch einfache Recherche mit Begriffen wie PWA, Framework, Bootstrap, Angular, Vue und vielem mehr konfrontiert. Versucht man sich zu informieren, welches Framework nun am besten genutzt werden soll, wird man schnell erkennen, dass die Beantwortung dieser Frage häufig eher einer Lebensphilosophie als einer rationalen Entscheidungsfindung gleicht. Um mit Fakten ein wenig Licht ins Dunkle zu bringen hat dieser Artikel zum Ziel Flask und Django zu vergleichen. Beides sind prominente und weit verbreitete Webframeworks in der Sprache Python, die aktuell auf hohe Beliebtheitswerte zurückgreifen kann.

Einführung

Python ist eine interpretierte Programmiersprache, welche verschiedene Paradigmen, wie z.B die objektorientierte und die funktionale Programmierung unterstützt. Durch den knappen Programmierstil, welcher auf Einrückungen und nicht auf geschweiften Klammern basiert, ist der Code einfach strukturiert. Zusätzlich durch die klare und übersichtliche Syntax gilt Python als eine einsteigerfreundliche Programmiersprache.

Ursprünglich wurde Python in den Neunzigerjahren am Amsterdamer „Centrum Wiskunde & Informatica“ als Nachfolger der Lehrsprache ABC entwickelt. Dabei hat der Name selbst nichts mit der Schlange zu tun. Es wird dabei die englische Komikergruppe „Monty Python“ als Vorbild genommen (Bürkle & Augsten, 19). Bis vor kurzem liefen die Versionen Python2 und Python3 noch parallel. Jedoch wurde der Support für Python2 dieses Jahr nun offiziell eingestellt.

Das Webframework Flask wird auch als Microframework betitelt, welches einen Fokus auf kleine Applikationen mit geringeren Anforderungen legt. Django geht eher in die Richtung von großen Projekten und einem gebündelten All-In-One-Paket. Während Flask dem Entwickler selbst die Möglichkeit gibt, sich seine zu nutzenden Komponenten und Tools selbst auszuwählen, so gibt Django diese dem Entwickler weitestgehend vor. So stellt sich gleich zu Beginn die Frage (zumindest hat sie sich dem Autor dieses Artikels gestellt), wie die zu nutzenden Datenbanktechnologien auszusehen haben. Django beinhaltet ein eigenes ORM (Object Relational Mapping) während Flask dem Entwickler hier keine Vorgaben liefert. Die beliebteste und weitverbreiteste ORM ist SQLAlchemy.

Um eine bessere Einschätzung über Flask und Django zu erhalten, wird in diesem Blog zwei Mal die gleiche Homepage mit den jeweiligen Frameworks erstellt.

Aufbau der Webseite

Im Folgenden wird aufgezeigt, wie sich das Vorhaben eine kleine Webseite zu gestalten mit beiden Frameworks verwirklichen lässt. Dazu sind folgende Anforderungen zu beachten:

  • Es sollte eine Public API genutzt werden, um Daten zu laden
  • Es werden Datenbankfunktionalitäten getestet
  • Die Webseiten sollen 1:1 gleich aussehen

Als API wird PokéAPI genutzt. PokéAPI stellt über RESTful-Services Daten zu (fast) allen Pokémon, die es inzwischen gibt, zur Verfügung. Pokémon (Kurzschreibweise für Pocket Monsters) wurde als Game Boy Spiel 1996 von Nintendo veröffentlicht. Das Kernkonzept bestand aus dem Sammeln aller 151 Pokémon und dem Trainieren und Kämpfen mit diesen. Pokémon besitzen eigene Basiswerte für Angriff, Verteidigung, Initiative und Lebenspunkte. Gesammelte Informationen werden durch das Fangen von Pokémon in einer Enzyklopädie namens Pokédex während des Spielverlaufs freigeschaltet.

Aufgrund der guten Dokumentation der API und der Vielfalt an verschiedenen Informationen, die die kleinen Kampfmonster mit sich bringen, eignet sich die API perfekt für das Vorhaben, öffentliche Daten für eine Webseite zu nutzen. Das Endresultat ist ein Pokédex mit weiterführenden Informationen der einzelnen Pokémon.

Das fertige Projekt kann auf Github in folgenden zwei Repositories angeschaut werden:

Im folgenden wird Schritt für Schritt erklärt, was getan wurde, um das dort zur Verfügung stehende Ergebnis zu erreichen. Leser, die weitergehende Informationen benötigen, werden auf die umfangreichen Dokumentationen von Flask (Ronacher, 2010) und Django (Holovaty & Willison, 2005) verwiesen, welche auch für diese Arbeit als gut strukturierte Informationsquelle dienten.

Vorbedingung: Python installieren

Um Python zu installieren, gibt es verschiedene Wege. Für Windows kann man auf der offiziellen Python Website die aktuelle Version herunterladen. Linux-Distributionen bieten über den integrierten Package Manager die Möglichkeit, Python ganz einfach über die Konsole zu installieren. Ähnliches kann man unter Windows auch mit Chocolatey erreichen.

Bei der Installation unter Windows ist es wichtig, dass bei „Add Python to PATH“ der Haken gesetzt wird, da man Python sonst nicht über die CLI (Command Line Interface) nutzen kann ohne den Pfad zur Anwendung selbst anzugeben.

Initialisierung der jeweiligen Projekte

Nun müssen die Python Packages für Flask und Django heruntergeladen werden. Best Practice ist, dass man zunächst ein sogenanntes Virtual Environment erstellt. Dabei handelt es sich um eine vollständige Kopie des Python-Interpreters (Python Software Foundation, Virtual Environments and Packages, 2020). Wenn man Pakete in einer virtuellen Umgebung installiert, ist der systemweite Python-Interpreter nicht betroffen, nur die Kopie. Angenommen man würde ein Package systemweit zur Verfügung stellen und eine Webseite mit Flask 0.10.0 erstellen, so könnten sich Probleme ergeben, wenn ein weiteres Projekt auf Flask 0.11.0 aufbaut. Die Lösung beliebige Versionen genutzter Pakete für jede Anwendung zu installieren, besteht also darin, für jede Anwendung ein anderes Virtual Environment zu verwenden. Mit einer passenden IDE, wie z.B. PyCharm, kann ein Virtual Environment beim Erstellen eines Projekts schnell hinzugefügt werden.

Erstellung eines neuen Projekts in PyCharm

Aber auch ohne IDE ist dies einfach zu regeln. Dazu muss nur innerhalb des Projektordners folgender Code in der CLI ausgeführt werden:

python3 -m venv venv

Nun, da ein Virtual Environment erstellt ist, kann es mit einem weiteren Befehl aktiviert werden. Daraufhin können Flask bzw. Django in zwei separaten Projekten installiert werden.

venv\Scripts\activate
(venv) pip install flask

Nun geht es darum, das Grundgerüst zu erstellen. Da Flask als Microframework betitelt wird, hat der Entwickler es selbst in der Hand, wie seine App auszusehen hat. Die folgende Abbildung zeigt, wie das Beispielprojekt aufgebaut wurde.

Projektstruktur in Flask

Das Ganze hat auch zu bedeuten, dass man jegliche Datei und jeglichen Ordner selbst anlegen muss. Demgegenüber macht Django es einem sehr einfach. Um die komplette Grundstruktur zu erstellen, genügen folgende zwei Befehle in der CLI

django-admin startproject app
python manage.py startapp pokedex

Dabei wird zunächst das Projekt initialisiert, welches eine App namens pokedex bekommt.

Projektstruktur in Django

In beiden Projekten müssen die HTML-Templates, die Datei methods.py und die Konfiguration innerhalb des Projekts zusätzlich erstellt werden.

Anbindung einer Datenbank

Um Daten zu persistieren, wird eine Datenbankanbindung benötigt. Die Handhabung der Datenbankmodelle ähnelt sich bei beiden Frameworks, jedoch existieren feine Unterschiede bei der erstmaligen Initialisierung. Wie schon zuvor erwähnt, besitzt Django von Haus aus eine ORM-Unterstützung. Diese muss bei Flask erst als Erweiterung durch den Package-Manager pip heruntergeladen werden. Dazu werden Flask-SQLAlchemy und Flask-Migrate genutzt. Vorteilhaft an SQLAlchemy ist, dass es nicht nur für eine, sondern für viele relationale Datenbanken geeignet ist. SQLAlchemy unterstützt eine lange Liste von Datenbank-Engines, darunter die populären MySQL, PostgreSQL und SQLite. Ein Vorteil daran ist, dass man für die Entwicklung eine einfache SQLite-Datenbank nutzen kann, welche dann zum produktiven Go-Live durch eine robustere MySQL- oder PostgreSQL-Datenbank ersetzt werden kann, ohne dass sich etwas an der Anwendung ändert. Zu Flask-Migrate wird zu einem späteren Zeitpunkt im Artikel noch Bezug genommen.

Zunächst muss eine config.py im root Verzeichnis erstellt werden und die benötigte Konfiguration getätigt werden:

# Define the application directory
import os
BASE_DIR = os.path.abspath(os.path.dirname(__file__))

# Statement for enabling the development environment
DEBUG = True
THREADS_PER_PAGE = 2
class Config(object): 
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(BASE_DIR, 'app.db')
    SQLALCHEMY_TRACK_MODIFICATIONS = False

Um nicht abhängig vom Speicherort des Projekts zu sein, wird das BASE_DIR anhand des Pfades der Datei ermittelt. THREADS_PER_PAGE soll laut Flask-Dokumentation auf 2 gesetzt werden. Die Konfiguration der Datenbank beinhaltet den Speicherort der Datenbank selbst (hier app.db gennant). Die Konfigurationsoption SQLALCHEMY_TRACK_MODIFICATIONS ist auf False gesetzt, damit der Anwendung nicht jedes Mal signalisiert werden soll, wenn eine Änderung in der Datenbank vorgenommen wird.

Weiterhin wird eine run.py im Root-Verzeichnis mit folgendem Inhalt erstellt:

# Run a test server.
from app import app
app.run(host='127.0.0.1', port=8080, debug=True)

Zum Schluss muss noch die __init__.py Datei im App-Ordner erstellt werden, die beim Ausführen von Flask gestartet wird:

from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)

from app import routes, models

Darin wird die App initialisiert und ihr die zuvor erstellte Konfiguration zugewiesen. Um unsere Datenbank nutzen zu können, wird diese auch hier initialisiert. Weiterhin bekommt Migrate hier eine Instanz.

Für Django muss in der settings.py im App-Ordner nur die Engine angepasst werden. Dies sieht wie folgt aus:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

Da die settings.py zu dem Zeitpunkt schon geöffnet ist, können folgende Anpassungen schon jetzt vorgenommen werden:

  • Der LANGUAGE_CODE kann auf „de-de“ geändert werden
  • Die TIME_ZONE sollte auf „Europe/Berlin“ geändert werden
  • INSTALLED_APPS muss um unsere App pokedex und um mathfilters erweitert werden

In INSTALLED_APPS wird verwaltet, welche Applikationen beim Aufrufen der Django-Website genutzt werden. Da die App pokedex den gesamten Code beinhaltet, der für das Frontend benötigt wird, muss diese hier eingetragen sein. Die App django-mathfilters muss für Django auch über pip installiert werden. Diese wird bei den Templates nützlich sein.

Für das Arbeiten mit der Datenbank muss ein sogenanntes Model erstellt werden. Ein Model enthält alle wesentlichen Felder und Verhaltensweisen der Daten, die in der Datenbank gespeichert werden. Im Endeffekt wird das Modell definiert, sodass klassische SQL-Queries nicht mehr benötigt werden, da die Datenbankoperationen direkt im Pythoncode stattfinden können. Die Vorgehensweise ist bei beiden Frameworks nahezu identisch:

  • Erstellung eines Models
  • Initialisierung von Migrations (nur Flask)
  • Erstellung einer Migration
  • Ausführung einer Migration

Model erstellen

Das Model eines Pokemon wird mit folgendem ERD beschrieben:

In beiden Frameworks wird eine models.py erstellt, die je nach Framework eine etwas andere Schreibweise hat. Dem interessierten Leser wird geraten, sich die Dateien in den hinterlegten GitHub-Projekten anzuschauen.

Kurz zusammengefasst erbt in beiden Frameworks das Model Pokemon von der zugehörigen Model Base Class. Darin werden die einzelnen Felder für die Datenbank definiert. Man kann durch optionale Argumente den primaryKey definieren oder auch Felder als unique kennzeichnen.

Die __repr__ Methode zeigt Python, wie das Objekt einer solchen Klasse bei einem print Statement auszusehen hat. Dies ist z.B. fürs Debugging sehr nützlich.

Initialisierung der Migrations

Das zuvor erstellte Model definiert die initiale Datenbankstruktur. Möglicherweise kommt es jedoch im Laufe der Entwicklung zu Änderungen von genau dieser. Beispiele dafür könnten neue Anforderungen sein, die im Planungsprozess nicht beachtet wurden oder auch neue Erkenntnisse während des Entwicklungsprozesses. Hier kommen Migrations ins Spiel. Durch diese Funktion, die zuvor für Flask bereitgestellt wurde und in Django schon integriert ist, können strukturelle Änderungen stattfinden, ohne dass man die Datenbank komplett neu aufsetzen muss. Im Falle von Flask muss das im Projekt vorhandene Migrations-Repository mit folgendem Kommando in der CLI zunächst erstellt werden:

flask db init

Erstellung von Migrations

Nun wird die initiale Migration erstellt. Dazu wird in Django folgender Befehl ausgeführt

python manage.py makemigrations pokedex

Mit diesem Befehl wird dem Django Framework gezeigt, dass es Änderungen im Model gab bzw. dass ein neues Model angelegt wurde, sodass dies als Migration gespeichert werden soll. Im Gegensatz zu Flask wird hier der vorherige Schritt integriert.

Dazu analog wird bei Flask folgendes ausgeführt

flask db migrate

Die Migrations werden damit angelegt, jedoch noch nicht ausgeführt. Gedanklich kann man sich das auch als eine Versionierungsmöglichkeit der Datenbank selbst vorstellen.

Eine Migration durchführen

Nun kommt der spannende Teil: die Datenbank wird aufgesetzt und erstellt. Die Migrations (und die Änderungen, die dort stattgefunden haben) werden nun mit folgenden Befehlen für Flask und Django ausgeführt:

flask db upgrade
python manage.py migrate

Somit ist die Datenbank aufgesetzt und kann durch das Model direkt mit Pythoncode angesprochen werden.

API abfragen und Daten persistieren

Die ausgewählte Public API eignet sich hervorragend, um eine variationsreiche Menge an Daten zu bekommen, die im zu erstellenden Frontend anschaulich dargestellt werden sollen. Jedoch existieren Beschränkungen von Seiten der Betreiber. Jeder Request darf höchstens 100 mal am Tag ausgeführt werden. Im Falle einer Beispielwebsite ist dies nicht von großer Bedeutung, jedoch wirkt sich dies auf einen möglichen Live-Auftritt aus. Die PokéAPI empfiehlt, die abgefragten Daten zu speichern. Dies sollte nun kein Problem mehr darstellen, da die Datenbanken bei beiden Frameworks konfiguriert und initialisiert wurden.

Um Abfragen in Richtung PokéAPI zu tätigen, werden in beiden Projekten die Methoden in der methods.py genutzt. Um einen HTTP-Request abzusetzen, wird in Python das requests Package benötigt, welches wieder über pip zur Verfügung gestellt wird.

def get_request(url):
    r = requests.get(url)
    return r.json()

def get_pokedex():
    return get_request('https://pokeapi.co/api/v2/pokedex/1')

def get_pokemon(pokemon):
    return get_request('https://pokeapi.co/api/v2/pokemon/{}'.format(pokemon))

get_requests(url) bekommt als Parameter die URL, welche über einen HTTP-GET-Request angefragt wird. Da PokéAPI keine Sicherheitsmechanismen, wie z.B. Bearer-Token oder OAuth2 nutzt, kann hier ein einfacher Request abgesendet werden. Das requests Package bietet einem auch sofort die Möglichkeit, den Response-Body, welcher eine JSON beinhaltet, zu parsen und als Dictionary zurückzugeben.

Die Methoden get_pokedex() und get_pokemon(pokemon) nutzen get_requests(url), um die jeweils benötigten Daten zurückzugeben. Dabei wird der jeweils benötigte API-Endpunkt mitgegeben.

Um die gewonnenen Daten in die Datenbank zu speichern, wird die check_database() Methode genutzt, die in den GitHub-Repositories angesehen werden kann. Diese unterscheidet sich bei beiden Frameworks nur minimal. Die Unterschiede sind bei der Handhabe des Model-Objects und bei der Speicherung in der Datenbank zu finden.

Daten beim Aufrufen durch den Browser darstellen

Da nun das komplette Grundgerüst steht, muss nur noch definiert werden, was passieren soll, wenn der Server über eine URL aufgerufen wird. Hier gibt es wieder größere Unterschiede zwischen Flask und Django.

In Flask nutzt man dafür die routes.py:

from flask import render_template

from app import app
from app.models import Pokemon
from app.methods import check_database

@app.route('/')
@app.route('/dex')
def dex():
    check_database()
    pokemon_list = Pokemon.query.all()
    return render_template('dex.html', title='Entire National Dex', pokemons=pokemon_list)

@app.route('/<pokemon>')
def pokemon_page(pokemon):
    pokemon = Pokemon.query.filter_by(name=pokemon).first() or Pokemon.query.filter_by(id=pokemon).first()
    return render_template('pokemon.html', title=pokemon, pokemon=pokemon)

@app.route(‚/‘) ist ein Python-Dekorator, den Flask zur Verfügung stellt, um URLs in der Anwendung auf einfache Weise Funktionen zuzuweisen. Der Dekorator teilt der App mit, dass immer, wenn ein Benutzer die gewünschte Domain unter der angegebenen .route() besucht, die Funktion dex() ausgeführt werden soll. Dabei können noch weitere Routes angegeben werden, die diese Funktion ausführen sollen.

In Falle des hier aufgezeigten Projekts wird beim initialen Aufrufen der Seite die zuvor erwähnte check_database()-Methode ausgeführt, mit der die Datenbank auf ihre Vollständigkeit überprüft wird. Danach wird diese durch unser Modell komplett ausgelesen. Nun kommen die sogenannten Templates ins Spiel. Dabei handelt es sich um Vorlagen, mit denen das auszugebende HTML generiert wird. In Flask wird dafür die Methode render_template() genutzt. Dieser Methode wird zunächst das Template selbst (‚dex.html‘) als auch die darin verwendeten Variablen übergeben. Als Template-Engine wird bei Flask Jinja2 verwendet, welches auf der Django Template-Engine basiert. Dadurch sind die Templates bei beiden Frameworks fast identisch. Feine Unterschiede, die dennoch existieren, können zu Fehlern führen, welche ungeübten Personen einen enormen Zeitaufwand bescheren.

Anhand des folgenden Snippets aus einem Template kann schnell aufgezeigt werden, wie die Logik in den Template Engines funktioniert:

<head>
    {% if title %}
    <title>{{ title }}</title>
    {% else %}
    <title>Welcome to a simple Pokédex</title>
    {% endif %}
</head>

Das Template nimmt die Struktur einer HTML-Datei ein, die durch eine ergänzende Syntax dynamische Regeln einbinden kann. In diesem Beispiel sieht man, dass das <title>-Element anhand der übergebenen Variable gesetzt wird. Ist diese nicht vorhanden, so wird ein Standardtext genutzt.

Da dem Template die gesamte Liste an Pokémon, die in der Datenbank gespeichert sind, übergeben wird, wird für jedes Pokémon eine eigene Kachel erzeugt.

Aufruf der Flask-Website über den Browser

Um das gleiche Ergebnis in Django zu erhalten, muss zuvor alles konfiguriert werden. In der Datei urls.py unseres gesamten Projekts müssen zunächst die genutzten Pfade auf unsere App pokedex verweisen.

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('pokedex.urls')),
    path('pokedex/', include('pokedex.urls')),
]

Darüber hinaus existiert noch eine weitere Datei namens urls.py innerhalb unserer App pokedex. In dieser wird nun, ähnlich wie bei der routes.py bei Flask definiert, was beim Aufruf einer URL geschehen soll. Darin wird zunächst der Path selbst, als auch auf die Methode, die in der views.py vorhanden sein muss, verwiesen.

from django.urls import path
from . import views

urlpatterns = [
    path('', views.pokedex, name='Pokedex'),
    path('<str:pokemon>/', views.pokemon, name='Pokemon')
]

Die views.py ist genauso aufgebaut wie die routes.py in Flask, mit dem kleinen Unterschied, dass der app.routes()-Dekorator nicht vorhanden ist, das Rendering des Templates etwas anders bewerkstelligt wird und der Aufruf der Datenbank durch das Model geringfügig anders aussieht:

from django.http import HttpResponse
from django.template import loader

from .methods import check_database
from .models import Pokemon

def pokedex(request):
    check_database()
    pokemon_list = Pokemon.objects.all()
    template = loader.get_template('dex.html')
    context = {
        'title': 'Entire National Dex',
        'pokemons': pokemon_list,
    }
    return HttpResponse(template.render(context, request))

def pokemon(request, pokemon):
    pokemon = Pokemon.objects.filter(name=pokemon).first() or Pokemon.objects.filter(id=pokemon).first()
    template = loader.get_template('pokemon.html')
    context = {
        'title': pokemon,
        'pokemon': pokemon,
    }
    return HttpResponse(template.render(context, request))

Im Falle der Methoden pokedex() bzw. dex() gibt es keine Unterschiede zwischen den Templates in beiden Frameworks.

Zusätzlich gibt es noch die Möglichkeit, sich einzelne Pokémons mit zusätzlichen Daten anzeigen zu lassen. Die Methoden pokemon() bzw. pokemon_page() wird dafür eine Variable mitgegeben. Diese Variable wird aus der Route bzw. dem Path extrahiert und der Methode zur Verfügung gestellt. Mit dieser Variable wird in der Datenbank nach dem entsprechenden Pokémon gesucht und ein weiteres Template (pokemon.html) genutzt. Dadurch kann, wenn man die Route /Pikachu oder /25 im Browser aufruft, das bekannteste Maskotchen der Pokémonwelt angesehen werden.

Die Browserseite zum Pokémon Pikachu

Starten des Testservers

Das Starten der Server geht einfach über die Kommandozeile. Durch die zuvor getätigten Konfigurationen innerhalb der __init__.py (Flask) und der manage.py (Django) müssen nur folgende Befehle für das jeweilige Framework ausgeführt werden

run app
manage.py runserver

Dadurch werden die Ports 8080 (Flask) und 8000 (Django) auf localhost freigegeben.

Über die in der Konsole angezeigte URL kann das Ergebnis im Browser geöffnet werden. Diese Methode dient zu Entwicklungszwecken und sollte nicht auf produktiven Umgebungen ausgeführt werden. Vollwertige Deployments müssen noch durchgeführt werden, um die gewünschte Webseite live zu setzen.

Fazit

Nachdem anhand von beiden Frameworks gezeigt wurde, wie eine einfache Webseite, die Daten über eine Public API abruft, erstellt werden kann, sollte klar geworden sein, dass sich das allgemeine Vorgehen sehr ähnelt. Die Weisheit „Lerne Pattern, nicht Sprachen oder Frameworks“ wird bestätigt. Trotzdem sind die Einsatzzwecke für beide Frameworks unterschiedlich.

Hervorstechende Ähnlichkeiten sind, dass beide Webframeworks auf Python basieren, Open Source-Projekte sind, eine Template Engine besitzen und man ORM nutzen kann (auch wenn bei Flask diese Funktionalität separat hinzugefügt werden muss).

Flask bietet eine unvergleichliche Flexibilität, da es dafür vorgesehen ist, erweitert zu werden. Gerade bei größeren Projekten kann ein Entwicklerteam auf seine gesamte Erfahrung hinsichtlich Design Patterns, Skalierbarkeit und Testen zurückgreifen, um Flask optimal nutzen zu können. Das initiale Setup kann zwar länger dauern, jedoch können so Abweichungen vom in Django vorgesehenen Weg vorgenommen werden. Da Django einem Entwickler sein All-In-One-Paket bietet, wird damit zwangsläufig auch ein Teil der Entwicklungsfreiheit genommen (Herman, 2019).

Aufgrund der erzwungenen Struktur eignet sich Django aber auch für größere Projekte mit größeren Teams, um das Management unterschiedlicher, vielfältiger Dependencies zu erleichtern. Flask wird auch für kleinere, unkompliziertere Projekte empfohlen, welche einen definierten Anwendungsfall besitzen.

Es lässt sich derzeit kein Trend erkennen, welches der beiden Frameworks mehr Zukunftssicherheit bietet. Sowohl Flask (Netflix, Airbnb, Uber oder Reddit) als auch Django (Instagram, Spotify, Youtube oder Firefox) werden heutzutage von wichtigen Unternehmen im Web-Business genutzt (Luiza | team member merixstudio, 2020).

Aus Sicht des Autors lässt sich zusammenfassend festhalten, dass Flask für alljene Entwickler geeignet ist, die sich ein eigenes Verständnis für die verwendeten Technologien und Packages aneignen möchten. Man schärft sein Wissen z.B. über das Testen wie auch Best Practices der Webentwicklung. Django nimmt einem diese Arbeit mit seinem All-In-One-Paket ab. Zudem lässt sich Gelerntes mit Flask einfach auf Django übertragen (Prax, 2019).

Literatur

Bürkle, A., & Augsten, S. (12. 07 19). Definition „Python (Programmiersprache)“. Abgerufen am 28. 05 2020 von Dev-Insider: https://files.vogel.de/vogelonline/pdfarticles/843/0/843060.pdf

Herman, M. (29. 09 2019). Django vs. Flask in 2019: Which Framework to Choose. Abgerufen am 24. 06 2020 von testdriven.io: https://testdriven.io/blog/django-vs-flask/

Holovaty, A., & Willison, S. (2005). Django The web framework for perfectionists with deadlines. (D. S. Foundation, Herausgeber) Abgerufen am 12. 06 2020 von https://www.djangoproject.com

Kent, S. L. (2001). The Ultimate History of Video Games: from Pong to Pokemon and beyond…the story behind the craze that touched our lives and changed the world. New York: Three Rivers Press.

Luiza | team member merixstudio. (24. 01 2020). https://www.merixstudio.com/blog/flask-vs-django-choosing-python-framework/. Abgerufen am 26. 06 2020 von merixstudio: https://www.merixstudio.com/blog/flask-vs-django-choosing-python-framework/

Prax, B. (17. 02 2019). Flask vs. Django? Abgerufen am 25. 06 2020 von DEV.to: https://dev.to/benprax/flask-vs-django-1l4k

Python Software Foundation. (24. 06 2020). List Comprehensions. Abgerufen am 24. 06 2020 von Python 3.8.3 documentation: https://docs.python.org/3/tutorial/datastructures.html

Python Software Foundation. (24. 06 2020). Virtual Environments and Packages. Abgerufen am 24. 06 2020 von Python 3.8.3 documentation: https://docs.python.org/3/tutorial/venv.html

Ronacher, A. (2010). Flask Web Development, one drop at time. Abgerufen am 12. 06 2020 von https://flask.palletsprojects.com/en/1.1.x/