Python - Django - 2 - View e Template

django python

Nel precedente articolo su Django abbiamo visto come creare e popolare il modello della nostra applicazione web tramite la shell.
Adesso vedremo come interagire con il modello creato attraverso la nostra applicazione web, studiando le altre due componenti del framework django: viste e template.

L'obiettivo di questo articolo sarà quello di creare e rendere funzionanti le seguenti pagine del sito:

  • Homepage
  • Pagina con elenco dei prodotti
  • Pagine per creazione, modifica ed eliminazione dei prodotti

Il codice completo è stato caricato sul nostro repository github. Per renderlo funzionante, vi consigliamo di seguire i passi descritti negli articoli di questa mini-serie.

Per lanciare il server locale e provare le modifiche, digitate sul terminale dalla cartella del progetto:

python manage.py runserver

Viste

Come era stato introdotto nel primo articolo su Django, quando si parla di vista ci riferiamo alla parte di business logic dell'applicazione (quello che in altri framework web sarebbe chiamato "controllore"). In generale, in Django, una vista è un callable python che prende in ingresso una richiesta web, la elabora, e restituisce una risposta web. Ho usato il termine callable perché una vista può essere definita sia come una funzione che come una classe.

Template

I template Django forniscono un modo per presentare le risposte web generate dalle viste attraverso pagine HTML, arricchite da componenti dinamiche proprie di Django. Nell'applicazione di esempio che andremo a sviluppare di articolo in articolo utilizzeremo il motore di template fornito dalla libreria. Per utilizzare un motore differente, sarà necessario modificare la variabile TEMPLATES del file settings.py.

Homepage

Per prima cosa vogliamo fare in modo che ogni volta che andiamo all'indirizzo http://127.0.0.1:8000/ecommerce/ sia visualizzata la homepage della nostra applicazione, con il titolo del sito e alcune informazioni, tra cui, per esempio, l'elenco delle case produttrici per le quali sono venduti i prodotti.
Dovremo perciò modificare i file ecommerce/views.py e ecommerce/urls.py, e creare una nuova cartella ecommerce/templates che andrà a contenere le pagine HTML dell'applicazione.

Url

All'interno di urlpatterns abbiamo inserito una configurazione la quale ci dice: ogni volta che è visitato l'indirizzo http://127.0.0.1:8000/ecommerce/ è chiamato il metodo index del modulo views. Il parametro name definisce un alias per richiamare direttamente la configurazione dai template.

View

Il metodo index ha il compito di ricevere la richiesta web incapsulata nell'oggetto request, ricavare dal modello l'elenco completo dei nomi delle case produttrici e passare il risultato al template index.html.
La risposta web è generata dal metodo render, che prende in ingresso la richiesta, il nome del template verso il quale indirizzarsi ed un dizionario di parametri che sarà aggiunto al contesto del template. Ciò significa che nella pagina index.html potremo fare riferimento al contenuto di case_produttrici che è stato salvato nel parametro con lo stesso nome del dizionario context.

Template

In questo semplice esempio di template possiamo vedere come l'elenco dei nomi delle case produttrici sia generato dinamicamente integrando i tag del Django Template Language ai tag HTML.
Il tag extends indica che index.html estende quanto definito nel template base_generic.html:

Il template base_generic.html funziona da contenitore per tutti i template che lo estendono. All'interno del tag head è dichiarato il title ed un elenco di collegamenti alle altre pagine del sito. Il contenuto del body è riempito dinamicamente utilizzando il tag {% block content %}. In questo caso, index.html si presenterà come mostrato nell'immagine:

La pagina dei contatti non sarà trattata in questa guida per la sua banalità. Viceversa, andiamo a vedere come creare la pagina con il catalogo dei prodotti.

Catalogo

Nel codice della pagina base dei template avrete notato il tag {% url 'products' %} all'interno di un link HTML verso il "Catalogo". In questo modo, cliccando sul link, il framework cerca nell'elenco delle configurazioni url se è presente un entry col nome products. In tal caso, viene chiamata la corrispondente vista.

Mentre per gestire la homepage abbiamo utilizzato una sola vista definita come metodo, per gestire il catalogo vedremo le differenze tra una vista creata come classe (Class Based View, CBV) ed una vista creata come funzione (Function Based View, FBV). Nello specifico utilizzeremo una CBV per gestire la visualizzazione dell'elenco dei prodotti e una FBV per gestire la visualizzazione dei singoli dettagli dei prodotti.

Url

Nella prima configurazione è dichiarato che all'indirizzo http://127.0.0.1:8000/ecommerce/products/ è mostrata una pagina con l'elenco dei prodotti presenti nel database. Tale pagina è gestita dalla CBV ProdottoListView. Il metodo as_view() restituisce un oggetto callable con le caratteristiche di una vista.

Nella seconda configurazione è dichiarato invece che agli indirizzi http://127.0.0.1:8000/ecommerce/products/NUMERO_INTERO è mostrata una pagina con i dettagli del prodotto con id NUMERO_INTERO. Il resto della configurazione è definito in maniera similare a quanto visto per la homepage.

View

La FBV product_show() non si allontana molto da quanto definito per la vista index(). Tramite la funzione get() di objects è recuperato un oggetto Prodotto, salvato nel context con chiave 'response', e passato il risultato al template detail.html.
La CBD ProductListView deriva dalla classe ListView fornita da Django, e come spiegato in precedenza gestisce la visualizzazione di un elenco di oggetti. Con gli attributi model e template_name sono definiti il tipo di modello da elencare ed il template al quale fare riferimento. Con il metodo get_context_data() è generato il context da passare al template. In questo caso, estendendo la classe ListView, si avrà all'interno del context una collezione di oggetti del tipo specificato in model.
Il vantaggio di usare CBV è quello di appoggiarsi direttamente a classi generiche già fornite dal framework Django in django.views.generic. Ciò significa però anche essere limitati dal comportamento di queste classi generiche, quindi in alcuni casi può convenire definirsi una FBV con una business logic adatta alla situazione. Tra le fonti citate, trovate un articolo a favore delle FBV ed uno a favore delle CBV per approfondimento.

Template

Il parametro object_list è definito all'interno del della classe ListView di Django. In questo esempio, per come abbiamo definito la classe ProductListView, conterrà tutti i prodotti salvati nel database. Per ogni elemento in object_list è stampato il nome ed il prezzo, ed è generato un link a {% url 'product_show' product_id=product.id %} che punta al template detail.html e che prende come parametro l'id del prodotto. Il template detail.html è mostrato di seguito:

Funzioni CRUD

Nel template products.html avrete notato la presenza di tre url particolari:

  • {% url 'product_new' %}
  • {% url 'product_edit' product.id %}
  • {% url 'product_delete' product.id %}

Queste configurazioni, insieme a {% url 'product_show' product.id %} si collegano alle viste che rappresentano le 4 operazioni CRUD, Create Read Update Delete, applicabili alle istanze delle tabelle del database.
La corrispondenza tra le viste e le operazioni è:

  • product_create(): Create
  • product_show(): Read
  • product_update(): Update
  • product_delete(): Delete

Le viste sono perciò create per fornire un'interfaccia verso le istanze Prodotto all'utente che utilizza l'applicazione. Nel prossimo tutorial vedremo come limitare tali operazioni solo ad una specifica categoria di utenti.

Url

Le tre configurazioni di coda di urlpatterns si collegano alle tre FBV per creare, modificare e cancellare un oggetto Prodotto.

View

Per facilitarci l'implementazione dei template di creazione e modifica di un oggetto Prodotto utilizziamo la classe ModelForm fornita da Django. ModelForm è una helper class che permette la generazione di oggetti per la gestione dei form a partire dalle classi di modello. Gli attributi model e fields della classe Meta permettono di specificare a quale modello il form deve fare riferimento e quali sono i campi che possono essere visualizzati/modificati.
Le FBV product_create() e product_update() utilizzano un oggetto ProductForm. La differenza sta nel fatto che mentre in product_create() il form è vuoto a meno che non sia stato inizializzato in sessione (richiesta POST), nel metodo product_update() il form è inizializzato con i campi caricati a partire dall'oggetto della classe Prodotto con id product_id. In entrambi i casi, se l'oggetto form è valido, il suo contenuto sarà salvato nel database tramite la funzione save() e la vista farà un redirect verso il template del catalogo 'products'. Viceversa, se l'oggetto form non è inizializzato, entrambe le viste renderizzeanno verso il template apposito product_form.html.
La FBV product_delete() invece prende direttamente un oggetto Prodotto con id product_id. Se il metodo di richiesta non è POST, mostra il template di conferma eliminazione dell'oggetto product_confirm_delete.hmtl. Una volta confermata l'eliminazione con il submit, il flusso sarà indirizzato di nuovo verso product_delete() la quale provvederà ad eliminare l'oggetto tramite la funzione delete().

Template

Grazie al metodo as_p il form è creato dinamicamente come tag p HTML, senza dover perdere tempo a dover scrivere gli input field nella pagina product_form.html.

Nel prossimo articolo della serie vedremo come limitare l'uso delle operazioni di creazione, modifica e cancellazione solo ad un gruppo imitato di utenti.

Per qualsiasi domanda, dubbio o precisazione, vi invito a lasciare un commento.
Vi ricordo che tutto il codice presentato lo potete trovare sul nostro repository github.

Fonti

Alessio Antonielli
Ingegnere informatico, appassionato di cinema, musica, videogiochi e serie tv. Insomma, le solite cose che vi aspettereste da un ex studente di Ingegneria Informatica, giusto per rafforzare lo stereotipo...
Python - Django - 2 - View e Template ultima modifica: 2017-05-02T12:02:47+00:00 da Alessio Antonielli


Advertisment ad adsense adlogger