Python che supporti Asyncio (> 3.4)
pipenv
è lo strumento che useremo per creare virtual environments.
Sul Pipfile
troviamo:
- sorgente
[[source]]
-> da dove i pacchetti vengono recuperati. Di defaultPyPi
- pacchetti
[[packages]]
-> pacchetti necessari !=pip freeze
. Non include la gerarchia di dipendenze, solamente quella primaria
Pipfile.lock
: utilizzato per creare deterministic builds
Per ogni pacchetto (anche quelli "impliciti") viene incluso nome, hashes, index, version.
Se non utilizzi il Pipfile.lock
potresti ottenere una build non deterministica. Ad esempio, se viene scaricata una versione più nuova di un pacchetto, può essere che si rompa qualche dipendenza.
pipenv --version
#Se non presente, creiamone uno nuovo
pipenv install django
pipenv shell
#Attenzione alla python_version
del Pipfile. Non è possibile richiedere una versione >=
, quindi cambiala a mano,
Dove si trova la cartella del virtual environment? pipenv --venv
Mostra una cartella nascosta .virtualenvs
con una sottocartella per ogni progetto. Se sposti la cartella dei sorgenti, ricordati di cancellare la cartella del venv.
Django è un web framework open-source, scritto in Python, che utilizza pattern architetturale Model-Template-View
- Model: definizione delle tabelle
- Template: pagina HTML
- View: logica della vista
- prototipazione veloce
- completo
- sicuro* se usato a valle di altri strumenti (reverse proxy et sim) in produzione
- scalabile
- versatile
Una volta attivato il venv, possiamo creare il progetto:
django-admin startproject [folder]
L'entry-point del progetto è contenuto in manage.py
, lo script che funge da proxy per la gestione dell'applicazione Django.
Questo script, legge inizialmente settings.py
BASE_DIR
è una costante che contiene il pathSECRET_KEY
è una costante da nascondere il produzione, mediante un file segreto o una variabile d'ambiente. Contiene un valore segreto, usato ad esempio come seme per crittografare le password.DEBUG
è una costante booleana, da porre aFalse
in produzioneALLOWED_HOST
è una lista di domini permessi; tipicamente usata solo in produzione, per evitare host-header attacks.INSTALLED_APPS
è una lista di applicazioni già fornite da Django che vogliamo abilitare per il progetto. In questa lista finiranno anche iadmin
ricorda che sono presenti solitamente 3 parti nella gestione di un sito web: sviluppatore, amministratore e utentiauth
applicazione di autenticazionesessions
- etc.
MIDDLEWARE
è una lista di middlewars che vogliamo abilitare per il progetto. Eg. CSRFROOT_URLCONF
è una lista di paths. Punta al modulourls.py
DATABASES
è un dizionario che definisce le informazioni necessarie all'interfacciamento con un DB. Di default il DBMS è sqlite3, memorizzato sudb.sqlite3
AUTH_PASSWORD_VALIDATORS
è una lista di validatori per le le password- user ... similarity -> non pass simile allo username
- minimum length
- common -> no pass comune
- etc.
LANGUAGE_CODE
è il locale del sito webDEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
imposta il tipo di chiave primaria utilizzata per le relazioni (-classi) memorizzate con il modello ORM. Questo implica che non è necessario aggiungere una PK all'interno delle classi. Concorrenza, atomicità e unicità sono gestiti da Django.
#Vedi host-header attack
Contiene una lista di URL patterns. È una lista di path
, sommariamente definiti come risorse accessibili dagli utenti.
È un modulo che crea una generica applicazione che sfrutta il protocollo WSGI per l'interpretazione di richieste e risposte
Come sopra, ma per il protocollo ASGI.
#Cerca ASGI vs websockets
python manage.py runserver
Almeno alla prima esecuzione, è necessaria la migrazione del DB: python manage.py migrate
Questo comando genera i file/la struttura del DB a partire dall'ORM.
Aggiungiamo un endpoint:
urlpatterns = [
#...
# endpoint, callback, alias
path("home/", home_page, name="homepage")
]
In views.py
aggiungiamo il callback:
def home_page(request):
response = 'Ciao!'
return HttpResponse(response)
Fatta una modifica, il server si riavvia da solo alla rilevazione di una modifica.
Posso usare la direttiva re_path
in urlpatterns
:
urlpatterns = [
...
re_path(r"^$|^/$|^/home$", home_page, name='homepage'), # Matchano 3 pattern: str vuota, /, /home
]
In questo modo le richieste inviate a uno di questi 3 url verrà gestita dalla view function (in futuro vedremo anche view classes) chiamata home_page
.
È un'altro dei vantaggi di una web application dinamica. Generazione o matching degli URL on-the-fly.
def function_view(request: HttpRequest) -> HttpResponse: ...
#Nota la migrazione è la procedura che consente di popolare il database.
Il dizionario della richiesta get contiene i parametri passati nella querystring.
Per evitare di dover castare ad ogni tipo possibile, scoprendo di quale tipo è una variabile mediante try-except, possiamo usare il type hinting di Django:
path("url_path/<int:eta>/<str:nome>/", view_fun, name="url_path")
Questo permette il raggiungimento di URL dinamici, che matchino i tipi richiesti dal path:
def view_fun(request, eta, nome): ...
logger.warning(...)
#Vedi logging
library https://docs.djangoproject.com/en/5.0/topics/logging/#topic-logging-parts-loggers
Il formato del logging è timestamp - url - protocol - response code.