- Modificato
Python ha diversi tools per semplificare lo sviluppo di applicazioni web dando una struttura canonica e un insieme di funzioni comuni, questi tools si chiamano appunto web frameworks.
Sono usati soprattutto per semplificazione, pattern MVC, gestione richieste e risposte HTTP, routing delle URL, accesso al database, sicurezza, gestione cookie, template e middleware (aggiunta di funzioni sulle richieste).
Ecco una classifica del livello di popolarità dei web frameworks più conosciuti. Fonte.
Flask e Django sono due approcci molto validi. Flask è un microframework che si caratterizza per la flessibilità offre una scelta ampia di tools installabili. Al contrario Django è un framework "all-inclusive" che offre una gamma più ampia di funzionalità integrate di default.
Django impone molti vincoli sulla struttura del codice ma con uno scopo ben definito: spingere gli sviluppatori a creare applicazioni con un design pulito. Mentre Flask offre maggiore libertà quindi bisognerà fare più esperienza per comprenderlo al meglio.
Entrambi sono gratuiti e le community sono vastissime, siti ufficiali: Flask e Django.
Struttura canonica:
Variabili e Strutture di Controllo:
Django:
<!-- file: index.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ heading }}</h1>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</body>
</html>
Python/Django view:
# file: views.py
from django.shortcuts import render
def index(request):
context = {
'title': 'Django Example',
'heading': 'List of Items',
'items': ['Item 1', 'Item 2', 'Item 3']
}
return render(request, 'index.html', context)
Jinja2:
<!-- file: index.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ heading }}</h1>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</body>
</html>
Python/Flask view:
# file: app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
title = 'Jinja2 Example'
heading = 'List of Items'
items = ['Item 1', 'Item 2', 'Item 3']
return render_template('index.html', title=title, heading=heading, items=items)
Differenze:
- Sintassi: Django usa {% %} per le strutture di controllo come i cicli for, mentre Jinja2 usa {% %} per entrambi, le variabili sono racchiuse tra {{ }}.
- Contesto: entrambi richiedono un contesto per rendere le variabili disponibili nelle strutture canoniche.
Filtri e Funzioniù
Django:
<!-- file: index.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ heading|upper }}</h1>
<ul>
{% for item in items %}
<li>{{ item|length }}</li>
{% endfor %}
</ul>
</body>
</html>
Jinja2:
<!-- file: index.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ heading|upper }}</h1>
<ul>
{% for item in items %}
<li>{{ item|length }}</li>
{% endfor %}
</ul>
</body>
</html>
Differenze:
- Filtri: entrambi supportano filtri per manipolare i dati direttamente nelle strutture canoniche ma la sintassi può variare.
URL dispatcher
L'URL dispatcher è una parte fondamentale per praticamente tutti i framework web. La sua funzione principale è associare gli URL delle richieste dei client alle funzioni o alle view appropriate. In Django l'URL dispatcher viene usato per definire come si dovrebbe rispondere alle richieste.
Definizione delle URL:
Nel file urls.py di ciascuna applicazione Django si può definire gli URL associati a diverse views.
# file: myapp/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('home/', views.home, name='home'),
path('about/', views.about, name='about'),
]
In questo esempio si definiscono due URL uno per la home e uno per about.
Collegamento delle URL:
# file: myproject/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('myapp/', include('myapp.urls')),
]
In questo caso tutte le URL definite in myapp/urls.py saranno disponibili sotto il percorso myapp/.
View functions:
La home usa render per generare una risposta HTML mentre la about restituisce una semplice risposta di testo.
# file: myapp/views.py
from django.shortcuts import render
from django.http import HttpResponse
def home(request):
return render(request, 'home.html')
def about(request):
return HttpResponse("About Us")
Molto importante perché è possibile gestire le richieste dei client in modo efficace e creare un'applicazione web ben strutturata.
Adatti per servizi web RESTful?
Django:
- Routing e URL Mapping: usa l'URL dispatcher come menzionato precedentemente per mappare le richieste agli URL delle viste ma a differenza di Flask, Django non presenta un approccio "esplicito" per richiamare le API RESTful.
- Serializzatori: Django ha un modulo (serializers) che semplifica la conversione dei dati in formati come JSON, questo è utile quando usiamo API RESTful perché si rappresentano i dati in quel formato.
- Classi di vista: Django usa classi di vista per gestire le richieste. Possono essere utilizzate anche per le API RESTful con Django REST Framework (DRF) tool aggiuntivo per Django che semplifica il tutto.
- Autenticazione e Autorizzazione: In Django è incluso un tool di autenticazione e autorizzazione che può essere usato anche nelle API RESTful. DRF fornisce tool per l'autenticazione basata su token, ruoli ecc.
Flask:
Estensibilità: Flask è più modulare e permette di scegliere librerie specifiche per gestire tutte le funzionalità come la serializzazione dei dati. Ad esempio Flask-RESTful è un'estensione di Flask che semplifica le API RESTful.
Minima configurazione di default: Il che significa che fornisce solo il minimo necessario per iniziare lasciando agli sviluppatori la libertà di estendere le funzionalità secondo necessità.
Conclusioni
Difficile stabilire qual è il migliore, la scelta dipende molto dal tipo di progetto, esperienza e obiettivi che dobbiamo raggiungere.
Django è ancora valido nel 2023? Direi proprio di si, basta vedere le statistiche! Il 40% dei progetti Python è basato proprio su quel framework!
Unire Django e Flask non ha molto senso anche se tecnicamente è possibile, hanno funzionalità sovrapposte e spesso gestiscono compiti simili in modi diversi quindi causerà confusione e complessità inutili.
Ecco una tabella per riassumere i punti toccati in questa discussione: