aboutsummaryrefslogtreecommitdiff
path: root/files/it/learn/server-side/django/forms/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'files/it/learn/server-side/django/forms/index.html')
-rw-r--r--files/it/learn/server-side/django/forms/index.html678
1 files changed, 0 insertions, 678 deletions
diff --git a/files/it/learn/server-side/django/forms/index.html b/files/it/learn/server-side/django/forms/index.html
deleted file mode 100644
index 80c0970f16..0000000000
--- a/files/it/learn/server-side/django/forms/index.html
+++ /dev/null
@@ -1,678 +0,0 @@
----
-title: 'Django Tutorial Part 9: Working with forms'
-slug: Learn/Server-side/Django/Forms
-translation_of: Learn/Server-side/Django/Forms
----
-<div> {{LearnSidebar}}</div>
-
-<div>{{PreviousMenuNext("Learn/Server-side/Django/authentication_and_sessions", "Learn/Server-side/Django/Testing", "Learn/Server-side/Django")}}</div>
-
-<p class="summary">In questo tutorial ti mostreremo come lavorare con i form HTML in Django e, in particolare, il modo più semplice per scrivere moduli per creare, aggiornare ed eliminare istanze di modelli. Come parte di questa dimostrazione, estenderemo il sito Web LocalLibrary in modo che i bibliotecari possano rinnovare libri e creare, aggiornare ed eliminare autori utilizzando i nostri moduli (anziché utilizzare l'applicazione di amministrazione).</p>
-
-<table class="learn-box standard-table">
- <tbody>
- <tr>
- <th scope="row">Prerequisiti:</th>
- <td>Completare il precedente tutorial, compreso: <a href="/en-US/docs/Learn/Server-side/Django/authentication_and_sessions">Django Tutorial Part 8: User authentication and permissions</a>.</td>
- </tr>
- <tr>
- <th scope="row">Obiettivi:</th>
- <td>Comprendere come scrivere form per ottenere informazioni dagli utenti e aggiornare il database. Per capire come le generiche viste di modifica dei form basate sulla classe possono semplificare enormemente la creazione di form per lavorare con un singolo modello.</td>
- </tr>
- </tbody>
-</table>
-
-<h2 id="Panoramica">Panoramica</h2>
-
-<p>Un <a href="/en-US/docs/Web/Guide/HTML/Forms">HTML Form</a>, o modulo, è un gruppo di uno o più campi/widget su una pagina Web, che può essere utilizzato per raccogliere informazioni dagli utenti per l'invio a un server. I moduli sono un meccanismo flessibile per la raccolta dell'input dell'utente perché ci sono widget adatti per inserire molti tipi diversi di dati, tra cui caselle di testo, caselle di controllo, pulsanti di opzione, selettori di date, ecc. I moduli sono anche un modo relativamente sicuro di condividere i dati con il server, poiché ci consentono di inviare i dati nelle richieste POST con la protezione dalle falsificazioni delle richieste cross-site.</p>
-
-<p>Anche se finora non abbiamo creato alcun modulo in questo tutorial, li abbiamo già incontrati nel sito di Django Admin. Ad esempio, lo screenshot seguente mostra un modulo per la modifica di uno dei nostri modelli <a href="/en-US/docs/Learn/Server-side/Django/Models">Book</a>, composto da un certo numero di elenchi di selezione e editor di testo.</p>
-
-<p><img alt="Admin Site - Book Add" src="https://mdn.mozillademos.org/files/13979/admin_book_add.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p>
-
-<p>Lavorare con i moduli Web può essere complicato! Gli sviluppatori devono scrivere HTML per il modulo, convalidare e bonificare correttamente i dati immessi sul server (e possibilmente anche nel browser), ripubblicare il modulo con messaggi di errore per informare gli utenti di eventuali campi non validi, gestire i dati quando sono stati inviati correttamente e infine rispondere all'utente in qualche modo per indicare il successo. <em>Django Forms</em> prende molto del lavoro da tutti questi passaggi, fornendo un framework che consente di definire i form e i loro campi a livello di codice, e quindi utilizzare questi oggetti per generare il codice HTML del modulo e gestire gran parte della convalida e dell'interazione dell'utente.</p>
-
-<p>In questo tutorial, ti mostreremo alcuni dei modi in cui puoi creare e lavorare con i moduli e, in particolare, in che modo le viste generiche del modulo di modifica possono ridurre in modo significativo la quantità di lavoro necessario per creare moduli da manipolare i tuoi modelli Lungo la strada, estenderemo la nostra applicazione LocalLibrary aggiungendo un modulo per consentire ai bibliotecari di rinnovare i libri della biblioteca e creeremo pagine per creare, modificare ed eliminare libri e autori (riproducendo una versione di base del modulo mostrato sopra per la modifica libri).</p>
-
-<h2 id="HTML_Forms">HTML Forms</h2>
-
-<p>Prima, una breve panoramica degli <a href="/en-US/docs/Learn/HTML/Forms">HTML Forms</a>. Consideriamo un semplice form, con un singolo campo di testo per inserire il nome di alcuni "team" e la relativa etichetta associata:</p>
-
-<p><img alt="Simple name field example in HTML form" src="https://mdn.mozillademos.org/files/14117/form_example_name_field.png" style="border-style: solid; border-width: 1px; display: block; height: 44px; margin: 0px auto; width: 399px;"></p>
-
-<p>Un form HTML è definito in un insieme di elementi dentro dei tag <code>&lt;form&gt;...&lt;/form&gt;</code>, contenenti almeno un elemento <code>input</code> di <code>type="submit"</code>.</p>
-
-<pre class="brush: html">&lt;form action="/team_name_url/" method="post"&gt;
-    &lt;label for="team_name"&gt;Enter name: &lt;/label&gt;
-    &lt;input id="team_name" type="text" name="name_field" value="Default name for team."&gt;
-    &lt;input type="submit" value="OK"&gt;
-&lt;/form&gt;</pre>
-
-<p>Mentre qui abbiamo solo un campo di testo per inserire il nome del team, un modulo può avere qualsiasi numero di altri elementi di input e le loro etichette associate. L'attributo <code>type</code> del campo definisce quale tipo di widget verrà visualizzato. Il <code>nome e l'ID</code> del campo vengono utilizzati per identificare il campo in JavaScript / CSS / HTML, mentre il <code>value</code> definisce il valore iniziale per il campo quando viene visualizzato per la prima volta. L'etichetta del team corrispondente viene specificata utilizzando il tag label (vedere "Immettere il nome" sopra), con un campo for che contiene il valore id dell'input associato.</p>
-
-<p>L'input  <code>submit</code>  verrà visualizzato come un pulsante (predefinito) che può essere premuto dall'utente per caricare i dati in tutti gli altri elementi di input nel modulo sul server (in questo caso, solo il <code>team_name</code>). Gli attributi del form definiscono il metodo HTTP utilizzato perinviare i dati e la destinazione dei dati sul server (<code>action</code>):</p>
-
-<ul>
- <li><code>action</code>: La risorsa / URL in cui i dati devono essere inviati per l'elaborazione quando viene inviato il modulo. Se questo non è impostato (o impostato su una stringa vuota), il modulo verrà inviato nuovamente all'URL della pagina corrente.</li>
- <li><code>method</code>: Il metodo HTTP utilizzato per inviare i dati: post o get.
- <ul>
- <li>Il metodo POST deve essere sempre utilizzato se i dati determinano una modifica al database del server, in quanto ciò può essere reso più resistente agli attacchi delle richieste di falsificazione intersito.</li>
- <li>Il metodo GET deve essere utilizzato solo per form che non modificano i dati dell'utente (ad esempio un form di ricerca). È consigliato quando vuoi essere in grado di aggiungere un segnalibro o condividere l'URL.</li>
- </ul>
- </li>
-</ul>
-
-<p>Il ruolo del server è innanzitutto quello di rendere lo stato del form iniziale - contenente campi vuoti o prepopolati con valori iniziali. Dopo che l'utente ha premuto il pulsante di invio, il server riceverà i dati del modulo con i valori del browser Web e dovrà convalidare le informazioni. Se il modulo contiene dati non validi, il server dovrebbe visualizzare nuovamente il modulo, questa volta con i dati immessi dall'utente nei campi e nei messaggi "validi" per descrivere il problema per i campi non validi. Una volta che il server riceve una richiesta con tutti i dati del modulo validi, può eseguire un'azione appropriata (ad esempio, salvare i dati, restituire il risultato di una ricerca, caricare un file, ecc.) E quindi avvisare l'utente.</p>
-
-<p>Come potete immaginare, la creazione dell'HTML, la convalida dei dati restituiti, la ri-visualizzazione dei dati inseriti con i rapporti di errore se necessario e l'esecuzione dell'operazione desiderata su dati validi possono richiedere un notevole sforzo per "avere ragione". Django rende tutto molto più semplice, eliminando parte del pesante codice ripetitivo.</p>
-
-<h2 id="Processo_di_Django_di_gestione_dei_form">Processo di Django di gestione dei form</h2>
-
-<p>La gestione dei form di Django utilizza tutte le stesse tecniche apprese in precedenti tutorial (per la visualizzazione di informazioni sui nostri models): la vista riceve una richiesta, esegue tutte le azioni richieste inclusa la lettura dei dati dai modelli, quindi genera e restituisce una pagina HTML ( da un modello, in cui passiamo un contesto contenente i dati da visualizzare). Ciò che rende le cose più complicate è che il server deve anche essere in grado di elaborare i dati forniti dall'utente e visualizzare nuovamente la pagina in caso di errori.</p>
-
-<p>Di seguito viene mostrato un diagramma di flusso del processo di gestione delle richieste di modulo da parte di Django, a partire da una richiesta per una pagina contenente un form (mostrato in verde).</p>
-
-<p><img alt="Updated form handling process doc." src="https://mdn.mozillademos.org/files/14205/Form%20Handling%20-%20Standard.png" style="display: block; height: 569px; margin: 0px auto; width: 800px;"></p>
-
-<p>Basandosi sul diagramma sopra, le cose che principalmente svolge Django nella gestione dei form sono:</p>
-
-<ol>
- <li>Mostra il modulo predefinito la prima volta che viene richiesto dall'utente.</li>
-</ol>
-
-<ul>
- <li>Il form può contenere campi vuoti (ad es. Se stai creando un nuovo record), oppure può essere precompilato con valori iniziali (ad es. Se stai cambiando un record o hai valori iniziali predefiniti utili).</li>
- <li>A questo punto, il form viene definito come non associato, poiché non è associato a nessun dato inserito dall'utente (sebbene possa avere valori iniziali).</li>
-</ul>
-
-<ol>
- <li>Riceve i dati da una richiesta di invio e li associa al modulo.
- <ul>
- <li>Collegare i dati al modulo significa che i dati inseriti dall'utente e gli eventuali errori sono disponibili quando è necessario visualizzare nuovamente il modulo.</li>
- </ul>
- </li>
- <li>Pulisce e valida i dati.
- <ul>
- <li>La pulizia dei dati esegue la disinfezione dell'input (ad esempio rimuovendo i caratteri non validi che potrebbero essere utilizzati per inviare contenuto dannoso al server) e li converte in tipi coerenti di Python.</li>
- <li>La convalida verifica che i valori siano appropriati per il campo (ad es. Sono nel giusto intervallo di date, non sono troppo corti o troppo lunghi, ecc.)</li>
- </ul>
- </li>
- <li>Se i dati non sono validi, visualizza nuovamente il modulo, questa volta con tutti i valori e i messaggi di errore compilati dall'utente per i campi del problema.</li>
- <li>Se tutti i dati sono validi, eseguire le azioni richieste (ad esempio, salvare i dati, inviare e-mail, restituire il risultato di una ricerca, caricare un file, ecc.)</li>
- <li>Una volta completate tutte le azioni, reindirizza l'utente a un'altra pagina.</li>
-</ol>
-
-<p>Django fornisce una serie di strumenti e approcci per aiutarti con le attività sopra descritte. La più fondamentale è la classe <code>Form</code>, che semplifica sia la generazione di moduli HTML che la pulizia / convalida dei dati. Nella prossima sezione, descriviamo come le form funzionano usando l'esempio pratico di una pagina per consentire ai bibliotecari di rinnovare i libri.</p>
-
-<div class="note">
-<p><strong>Note:</strong> Capire come si usa Form ti sarà d'aiuto quando discuteremo le classi di form più "di alto livello" di Django.</p>
-</div>
-
-<h2 id="Modulo_di_rinnovo_del_libro_utilizzando_una_Form_e_funzione_vista">Modulo di rinnovo del libro utilizzando una Form e funzione vista</h2>
-
-<p>Successivamente, aggiungeremo una pagina per consentire ai bibliotecari di rinnovare i libri presi in prestito. Per fare ciò creeremo un modulo che consenta agli utenti di inserire un valore di data. Daremo il campo con un valore iniziale di 3 settimane rispetto alla data corrente (il normale periodo di prestito) e aggiungiamo alcune convalide per garantire che il bibliotecario non possa inserire una data nel passato o una data troppo lontana nel futuro. Quando è stata inserita una data valida, la scriveremo nel campo BookInstance.due_back del record corrente. L'esempio utilizzerà una vista basata sulle funzioni e una classe Form.</p>
-
-<p>Le seguenti sezioni spiegano come funzionano le form le modifiche da apportare al nostro progetto LocalLibrary in corso.</p>
-
-<h3 id="Form">Form</h3>
-
-<p>La classe Form è il cuore del sistema di gestione delle form di Django. Specifica i campi nel modulo, il loro layout, i widget di visualizzazione, le etichette, i valori iniziali, i valori validi e (una volta convalidati) i messaggi di errore associati ai campi non validi. La classe fornisce anche i metodi per eseguire il rendering stesso nei modelli utilizzando formati predefiniti (tabelle, elenchi, ecc.) O per ottenere il valore di qualsiasi elemento (abilitando il rendering manuale a grana fine).</p>
-
-<h4 id="Dichiarare_un_Form">Dichiarare un Form</h4>
-
-<p>La sintassi della dichiarazione per una form è molto simile a quella per la dichiarazione di un modello e condivide gli stessi tipi di campo (e alcuni parametri simili). Questo ha senso perché in entrambi i casi dobbiamo garantire che ogni campo gestisca i giusti tipi di dati, sia vincolato a dati validi e abbia una descrizione per la visualizzazione / documentazione. I dati del modulo sono memorizzati nel file forms.py dell'applicazione, all'interno della directory dell'applicazione. Crea e apri il file locallibrary / catalog / forms.py. Per creare un modulo, importiamo la libreria dei moduli, deriviamo dalla classe Form e dichiariamo i campi del modulo. Di seguito è riportata una classe di modulo molto semplice per il modulo di rinnovo del libro della biblioteca: aggiungi questo al nuovo file:</p>
-
-<pre class="brush: python">from django import forms
-
-class RenewBookForm(forms.Form):
-    renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).")
-</pre>
-
-<h4 id="Form_fields">Form fields</h4>
-
-<p>In questo caso abbiamo un campo singolo <code><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#datefield">DateField</a></code> per inserire la data di rinnovo che renderizzerà in HTML con un valore vuoto, l'etichetta di default "Data di rinnovo:", e qualche utile testo di utilizzo: "Inserire una data tra ora e 4 settimane (predefinito 3 settimane)." Dato che nessuno degli altri argomenti opzionali è specificato, il campo accetterà le date usando il <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#django.forms.DateField.input_formats">input_formats</a>: YYYY-MM-DD (2016-11-06), MM/DD/YYYY (02/26/2016), MM/DD/YY (10/25/16), e sarà visualizzato con il widget standard <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#widget">widget</a>: <a href="https://docs.djangoproject.com/en/2.1/ref/forms/widgets/#django.forms.DateInput">DateInput</a>.</p>
-
-<p>Esistono molti altri tipi di campi form, che in gran parte riconoscerete dalla loro somiglianza con le classi di campo del modello equivalente: <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#booleanfield"><code>BooleanField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#charfield"><code>CharField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#choicefield"><code>ChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#typedchoicefield"><code>TypedChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#datefield"><code>DateField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#datetimefield"><code>DateTimeField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#decimalfield"><code>DecimalField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#durationfield"><code>DurationField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#emailfield"><code>EmailField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#filefield"><code>FileField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#filepathfield"><code>FilePathField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#floatfield"><code>FloatField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#imagefield"><code>ImageField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#integerfield"><code>IntegerField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#genericipaddressfield"><code>GenericIPAddressField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#multiplechoicefield"><code>MultipleChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#typedmultiplechoicefield"><code>TypedMultipleChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#nullbooleanfield"><code>NullBooleanField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#regexfield"><code>RegexField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#slugfield"><code>SlugField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#timefield"><code>TimeField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#urlfield"><code>URLField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#uuidfield"><code>UUIDField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#combofield"><code>ComboField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#multivaluefield"><code>MultiValueField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#splitdatetimefield"><code>SplitDateTimeField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#modelmultiplechoicefield"><code>ModelMultipleChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#modelchoicefield"><code>ModelChoiceField</code></a>.</p>
-
-<p>Gli argomenti comuni alla maggior parte dei campi sono elencati di seguito (questi hanno valori predefiniti sensibili):</p>
-
-<ul>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#required">required</a>: Se <code>True</code>, il campo non può essere lasciato bianco o <code>None</code>. I campi sono obbligatori per default, quindi se impostiamo <code>required=False</code> autorizzeremo dei campi blank nel form.</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#label">label</a>: L'etichetta da utilizzare quando si renderizza la pagina in HTML. Se la <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#label">label</a> non viene specificata, Django ne creerà uno dal nome del campo capitalizzando la prima lettera e sostituendo gli underscore con gli spazi (ad esempio la data di rinnovo).</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#label-suffix">label_suffix</a>: Di default i due punti vengono visualizzati dopo l'etichetta (ad esempio, data di rinnovo:). Questo argomento consente di specificare un suffisso diverso contenente altri caratteri.</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#initial">initial</a>: Il valore iniziale per il campo quando viene visualizzato il modulo.</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#widget">widget</a>: Il widget da mostrare.</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#help-text">help_text</a> (come visto sopra): testo di aiuto addizionale da mostrare per spiegare l'uso di un campo del form.</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#error-messages">error_messages</a>: Una lista di messaggi di errore per il campo. Puoi sovrascrivere tali messaggi coi tuoi se necessario.</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#validators">validators</a>: una lista di funzioni da richiamare quando il campo viene validato.</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#localize">localize</a>: Abilita la localizzazione nell'input dei dati del form. Vedere il link per maggiori dettagli.</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#disabled">disabled</a>: Il campo viene mostrato ma non è possibile validarlo, se questo attributo è <code>True</code>. Il valore di default è <code>False</code>.</li>
-</ul>
-
-<h4 id="Validazione">Validazione</h4>
-
-<p>Django offre numerosi posti dove puoi convalidare i tuoi dati. Il modo più semplice per convalidare un singolo campo è sovrascrivere il metodo clean_ &lt;nomecampo&gt; () per il campo che si desidera controllare. Quindi, ad esempio, possiamo effettuare una convalida richiedendo che i valori di renewal_date inseriti siano compresi tra ora e le 4 settimane future implementando clean_renewal_date () come mostrato di seguito.</p>
-
-<p>Aggiorniamo il file forms.py:</p>
-
-<pre class="brush: python"><strong>import datetime</strong>
-
-from django import forms
-<strong>from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
-</strong>
-class RenewBookForm(forms.Form):
-    renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).")
-
-<strong>    def clean_renewal_date(self):
-        data = self.cleaned_data['renewal_date']
-
-        # Check if a date is not in the past.
-        if data &lt; datetime.date.today():
-            raise ValidationError(_('Invalid date - renewal in past'))
-
-        # Check if a date is in the allowed range (+4 weeks from today).
-        if data &gt; datetime.date.today() + datetime.timedelta(weeks=4):
-            raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead'))
-
-        # Remember to always return the cleaned data.
-        return data</strong></pre>
-
-<p>Ci sono due cose importanti da notare. Il primo è che otteniamo i nostri dati usando self.cleaned_data ['renewal_date'] e che restituiamo questi dati indipendentemente dal fatto che vengano modificati alla fine della funzione. Questo passaggio ci porta i dati "puliti" e disinfettati da input potenzialmente non sicuri utilizzando i validatori predefiniti e convertiti nel tipo standard corretto per i dati (in questo caso un oggetto datetime.datetime di Python).</p>
-
-<p>La seconda è che se un valore è al di fuori di quelli ammessi solleviamo un errore di validazione <code>ValidationError</code>, specificando il testo di errore che vogliamo mostrare nel forme se un errore di validazione si è verificato. L'esempio sopra inoltre incapsula il testo in una funzione di traduzione di Django (vedi <a href="https://docs.djangoproject.com/en/2.1/topics/i18n/translation/">Django's translation functions</a>) <code>ugettext_lazy()</code> (importata come <code>_()</code>), che è una good practice in caso tu voglia tradurre il sito successivamente.</p>
-
-<div class="note">
-<p><strong>Note:</strong> Esistono molti metodi per validare i form, consultare <a href="https://docs.djangoproject.com/en/2.1/ref/forms/validation/">Form and field validation</a> (Django docs). Per esempio, in alcuni casi in cui si hanno diversi campi che dipendono uno dall'altro si può sovrascrivere la funzione <a href="https://docs.djangoproject.com/en/2.1/ref/forms/api/#django.forms.Form.clean">Form.clean()</a> e nuovamente sollevare una <code>ValidationError</code>.</p>
-</div>
-
-<p>Questo è tutto ciò di cui abbiamo bisogno per il form in questo esempio!</p>
-
-<h3 id="Configurazione_URL">Configurazione URL</h3>
-
-<p>Prima di creare la nostra vista, aggiungiamo una configurazione URL per la pagina dei rinnovi. Copia la seguente configurazione nella parte inferiore di locallibrary / catalog / urls.py.</p>
-
-<pre class="brush: python">urlpatterns += [
- path('book/&lt;uuid:pk&gt;/renew/', views.renew_book_librarian, name='renew-book-librarian'),
-]</pre>
-
-<p>La configurazione URL reindirizzerà tutti gli URL con formato <strong>/catalog/book/<em>&lt;bookinstance id&gt;</em>/renew/</strong> alla funzione <code>renew_book_librarian()</code> in <strong>views.py</strong>, e manderà l'id della <code>BookInstance</code> come parametro con nome <code>pk</code>. Il pattern matcha solamente se <code>pk</code> è un dato <code>uuid</code> correttamente formattato.</p>
-
-<div class="note">
-<p><strong>Note</strong>: Possiamo nominare qualsiasi cosa ci piaccia dai nostri dati di URL acquisiti anzichè "pk" , perché abbiamo il controllo completo sulla funzione di visualizzazione (non stiamo usando una classe di vista di dettaglio generica che si aspetta parametri con un certo nome). Tuttavia, pk abbreviazione di "chiave primaria", è una convenzione ragionevole da usare!</p>
-</div>
-
-<h3 id="Vista">Vista</h3>
-
-<p>Come discusso in <a href="#django_form_handling_process">Django form handling process</a>, la vista deve eseguire il rendering del modulo predefinito quando viene chiamato per la prima volta e quindi eseguire nuovamente il rendering con messaggi di errore se i dati non sono validi oppure elaborare i dati e reindirizzare a una nuova pagina se i dati sono validi. Per poter eseguire queste diverse azioni, la vista deve essere in grado di sapere se è stata richiamata per la prima volta per il rendering del modulo predefinito o un tempo successivo per convalidare i dati.</p>
-
-<p>Per i form che usano una <code>POST</code> per mandare infromazioni al server, il pattern più comune è fare in modo che sia la view ad eseguire i test verso la richiesta di <code>POST</code> (<code>if request.method == 'POST':</code>) identificare le richieste di convalida del modulo e GET (utilizzando un'altra condizione) per identificare la richiesta iniziale di creazione del modulo. Se si desidera inviare i dati utilizzando una richiesta GET, un approccio tipico per identificare se questa è la prima o successiva chiamata alla vista è leggere i dati del modulo (ad esempio, per leggere un valore nascosto nel modulo).</p>
-
-<p>Il processo di rinnovo del libro verrà scritto nel nostro database, quindi, per convenzione, utilizziamo l'approccio di richiesta POST. Il frammento di codice seguente mostra il modello (molto standard) per questo tipo di visualizzazione delle funzioni.</p>
-
-<pre class="brush: python">import datetime
-
-from django.shortcuts import render, get_object_or_404
-from django.http import HttpResponseRedirect
-from django.urls import reverse
-
-from catalog.forms import RenewBookForm
-
-def renew_book_librarian(request, pk):
-    book_instance = get_object_or_404(BookInstance, pk=pk)
-
-    # Se è una richiesta di tipo POST allora processa i dati della Form
-<strong>    if request.method == 'POST':</strong>
-
-        # Crea un'istanza della form e la popola con i dati della richiesta (binding):
-        form = RenewBookForm(request.POST)
-
-        # Controlla se la form è valida:
-        <strong>if form.is_valid():</strong>
-            # process the data in form.cleaned_data as required (here we just write it to the model due_back field)
-            book_instance.due_back = form.cleaned_data['renewal_date']
-            book_instance.save()
-
-            # reindirizza ad un nuovo URL:
-            return HttpResponseRedirect(reverse('all-borrowed') )
-
-    # Se la richiesta è GET o un altro metodo crea il form di default
-<strong>    else:</strong>
-        proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3)
-        form = RenewBookForm(initial={'renewal_date': proposed_renewal_date})
-
- context = {
- 'form': form,
- 'book_instance': book_instance,
- }
-
-    return render(request, 'catalog/book_renew_librarian.html', context)</pre>
-
-<p>Innanzitutto, importiamo il nostro form (RenewBookForm) e una serie di altri oggetti / metodi utili utilizzati nel corpo della funzione di visualizzazione:</p>
-
-<ul>
- <li><code><a href="https://docs.djangoproject.com/en/2.1/topics/http/shortcuts/#get-object-or-404">get_object_or_404()</a></code>: Ritorna uno specifico oggetto da un modello basato sulla propria chiave primaria, e solleva un'eccezione <code>Http404</code> (not found) se il record non esiste. </li>
- <li><code><a href="https://docs.djangoproject.com/en/2.1/ref/request-response/#django.http.HttpResponseRedirect">HttpResponseRedirect</a></code>: Questo crea un reindirizzamento verso un URL specificato (codice di stato HTTP 302).</li>
- <li><code><a href="https://docs.djangoproject.com/en/2.1/ref/urlresolvers/#django.urls.reverse">reverse()</a></code>: Questo genera un URL da un nome di configurazione URL e un set di argomenti. È l'equivalente Python del tag url che abbiamo utilizzato nei nostri templates.</li>
- <li><code><a href="https://docs.python.org/3/library/datetime.html">datetime</a></code>: Una libreria Python per manipolare date e ore.</li>
-</ul>
-
-<p>Nella vista, per prima cosa utilizziamo l'argomento pk in get_object_or_404 () per ottenere l'attuale BookInstance (se questo non esiste, la vista verrà immediatamente chiusa e la pagina mostrerà un errore "non trovato"). Se questa non è una richiesta POST (gestita dalla clausola else), creiamo il form predefinito che passa un valore iniziale per il campo renewal_date (come mostrato in grassetto sotto, questo è 3 settimane dalla data corrente). </p>
-
-<pre class="brush: python"> book_instance = get_object_or_404(BookInstance, pk=pk)
-
-    # Se la richiesta è GET o un altro metodo crea il form di default
-    else:
-        proposed_renewal_date = datetime.date.today() + datetime.timedelta(<strong>weeks=3</strong>)
-        <strong>form = RenewBookForm(initial={'renewal_date': proposed_renewal_date})</strong>
-
- context = {
- 'form': form,
- 'book_instance': book_instance,
- }
-
-    return render(request, 'catalog/book_renew_librarian.html', context)</pre>
-
-<p>Dopo aver creato il modulo, chiamiamo render() per creare la pagina HTML, specificando il modello e un contesto che contiene il nostro form. In questo caso, il contesto contiene anche il nostro BookInstance, che utilizzeremo nel modello per fornire informazioni sul libro che stiamo rinnovando.</p>
-
-<p>Tuttavia, se si tratta di una richiesta POST, allora creiamo il nostro oggetto form e lo popoliamo con i dati della richiesta. Questo processo è chiamato "binding" e ci consente di convalidare il form. Controlliamo quindi se il form è valido, eseguiamo tutto il codice di convalida su tutti i campi, compreso il codice generico per verificare che il nostro campo data sia effettivamente una data valida e la funzione clean_renewal_date() del nostro from specifico per verificare se la data è nella giusta fascia.</p>
-
-<pre class="brush: python">    # If this is a POST request then process the Form data
-    if request.method == 'POST':
-
-        # Create a form instance and populate it with data from the request (binding):
-<strong>        form = RenewBookForm(request.POST)</strong>
-
-        # Check if the form is valid:
-        if form.is_valid():
-            # process the data in form.cleaned_data as required (here we just write it to the model due_back field)
-            book_instance.due_back = form.cleaned_data['renewal_date']
-            book_instance.save()
-
-            # redirect to a new URL:
-            return HttpResponseRedirect(reverse('all-borrowed') )
-
- context = {
- 'form': form,
- 'book_instance': book_instance,
- }
-
-    return render(request, 'catalog/book_renew_librarian.html', context)</pre>
-
-<p>Se il form non è valido, viene richiamata nuovamente la funzione <code>render()</code>, ma questa volta il form viene passato al contesto con dei messaggi di errore. </p>
-
-<p>Se il form è valido, allora possiamo iniziare ad utilizzare i dati, accedendovi tramite l'attributo <code>form.cleaned_data</code> (ad es. <code>data = form.cleaned_data['renewal_date']</code>). Qui salviamo semplicemente i dati nel valore due_back dell'oggetto BookInstance associato.</p>
-
-<div class="warning">
-<p><strong>Importante</strong>: Anche se è possibile accedere ai dati del form direttamente tramite la richiesta, per esempio utilizzando <code>request.POST['renewal_date']</code> o <code>request.GET['renewal_date']</code> se invece stiamo utilizzando una richiesta GET, Ciò NON è raccomandabile. I dati ripuliti, sanificati, e validati, vengono convertiti in tipi adatti a Python.</p>
-</div>
-
-<p>Il passo finale nella manipolazione dei formè la direzione verso un'altra pagina, generalmente una "success" page. In questo caso utilizziamo <code>HttpResponseRedirect</code> e <code>reverse()</code> per ridirezionare alla vista nominata "<code>all-borrowed'</code> (creata come "challenge" in <a href="/en-US/docs/Learn/Server-side/Django/authentication_and_sessions#Challenge_yourself">Django Tutorial Part 8: User authentication and permissions</a>). Se non l'hai creata, ridireziona alla home page con URL '/').</p>
-
-<p>Questo è tutto ciò che ci serviva per il per la manipolazione dei form, ma dobbiamo ancora restringere gli accessi dei bibliotecari. Probabilmente dovremmo creare un nuovo permesso sull'oggetto <code>BookInstance</code> ("<code>can_renew</code>"), ma, per mantenere le cose più semplici, useremo solo il decoratore di funzione <code>@permission_required</code> con il nostro permesso esistente <code>can_mark_returned.</code></p>
-
-<p>La vista finale è quindi come di seguito. Copiare questo in fondo a <strong>locallibrary/catalog/views.py</strong>.</p>
-
-<pre><strong>import datetime
-
-from django.contrib.auth.decorators import permission_required</strong>
-from django.shortcuts import get_object_or_404
-from django.http import HttpResponseRedirect
-from django.urls import reverse
-
-from catalog.forms import RenewBookForm
-
-<strong>@permission_required('catalog.can_mark_returned')</strong>
-def renew_book_librarian(request, pk):
-    """View function for renewing a specific BookInstance by librarian."""
-    book_instance = get_object_or_404(BookInstance, pk=pk)
-
-    # If this is a POST request then process the Form data
-    if request.method == 'POST':
-
-        # Create a form instance and populate it with data from the request (binding):
-        form = RenewBookForm(request.POST)
-
-        # Check if the form is valid:
-        if form.is_valid():
-            # process the data in form.cleaned_data as required (here we just write it to the model due_back field)
-            book_instance.due_back = form.cleaned_data['renewal_date']
-            book_instance.save()
-
-            # redirect to a new URL:
-            return HttpResponseRedirect(reverse('all-borrowed') )
-
-    # If this is a GET (or any other method) create the default form.
-    else:
-        proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3)
-        form = RenewBookForm(initial={'renewal_date': proposed_renewal_date})
-
- context = {
- 'form': form,
- 'book_instance': book_instance,
- }
-
-    return render(request, 'catalog/book_renew_librarian.html', context)
-</pre>
-
-<h3 id="Il_template">Il template</h3>
-
-<p>Creiamo il template referenziato nella view (<strong>/catalog/templates/catalog/book_renew_librarian.html</strong>) e copiamo il codice sotto:</p>
-
-<pre class="brush: html">{% extends "base_generic.html" %}
-
-{% block content %}
- &lt;h1&gt;Renew: \{{ book_instance.book.title }}&lt;/h1&gt;
- &lt;p&gt;Borrower: \{{ book_instance.borrower }}&lt;/p&gt;
- &lt;p{% if book_instance.is_overdue %} class="text-danger"{% endif %}&gt;Due date: \{{ book_instance.due_back }}&lt;/p&gt;
-
-<strong> &lt;form action="" method="post"&gt;
- {% csrf_token %}
-  &lt;table&gt;
- \{{ form.as_table }}
- &lt;/table&gt;
- &lt;input type="submit" value="Submit"&gt;
- &lt;/form&gt;</strong>
-{% endblock %}</pre>
-
-<p>La maggior parte di questo sarà completamente familiare dai tutorial precedenti. Estendiamo il modello di base e quindi ridefiniamo il blocco del contenuto. Siamo in grado di fare riferimento a \{{book_instance}} (e alle sue variabili) perché è stato passato all'oggetto contesto nella funzione render (), e le possiamo usare per elencare il titolo del libro, il mutuatario e la data di scadenza originale.</p>
-
-<p>Il codice del form è relativamente semplice. Per prima cosa dichiariamo i tag del form, specificando dove deve essere inviato il form (action) e il metodo per inviare i dati (in questo caso un "POST HTTP") - se si richiama la panoramica dei moduli HTML nella parte superiore della pagina, un'azione vuota come mostrato, significa che i dati del modulo saranno postati all'URL attuale della pagina (che è ciò che vogliamo!). All'interno dei tag, definiamo l'input di invio, che un utente può premere per inviare i dati. Il {% csrf_token%} aggiunto appena dentro i tag del modulo fa parte della protezione dalle contraffazioni di Django.</p>
-
-<div class="note">
-<p><strong>Note:</strong> Aggiungi il {% csrf_token%} a ogni modello Django che crei che utilizza POST per inviare i dati. Ciò ridurrà la possibilità che le form vengano corrotte da utenti malintenzionati</p>
-</div>
-
-<p>Tutto ciò che rimane è la variabile di template \{{form}}, che abbiamo passato al template nel dizionario di contesto. Forse non sorprendentemente, se usato come mostrato, fornisce il rendering predefinito di tutti i campi del modulo, incluse le loro etichette, i widget e il testo della guida: il rendering è come mostrato di seguito:</p>
-
-<pre class="brush: html">&lt;tr&gt;
-  &lt;th&gt;&lt;label for="id_renewal_date"&gt;Renewal date:&lt;/label&gt;&lt;/th&gt;
-  &lt;td&gt;
-  &lt;input id="id_renewal_date" name="renewal_date" type="text" value="2016-11-08" required&gt;
-  &lt;br&gt;
-  &lt;span class="helptext"&gt;Enter date between now and 4 weeks (default 3 weeks).&lt;/span&gt;
-  &lt;/td&gt;
-&lt;/tr&gt;
-</pre>
-
-<div class="note">
-<p><strong>Note:</strong> Forse non è ovvio perché abbiamo solo un campo, ma, per impostazione predefinita, ogni campo è definito nella propria riga della tabella. Questo stesso rendering viene fornito se si fa riferimento alla variabile del template \{{form.as_table}}.</p>
-</div>
-
-<p>Se dovessi inserire una data non valida, avresti anche un elenco degli errori visualizzati nella pagina (mostrati in grassetto sotto).</p>
-
-<pre class="brush: html">&lt;tr&gt;
-  &lt;th&gt;&lt;label for="id_renewal_date"&gt;Renewal date:&lt;/label&gt;&lt;/th&gt;
-  &lt;td&gt;
-<strong>  &lt;ul class="errorlist"&gt;
-  &lt;li&gt;Invalid date - renewal in past&lt;/li&gt;
-  &lt;/ul&gt;</strong>
-  &lt;input id="id_renewal_date" name="renewal_date" type="text" value="2015-11-08" required&gt;
-  &lt;br&gt;
-  &lt;span class="helptext"&gt;Enter date between now and 4 weeks (default 3 weeks).&lt;/span&gt;
- &lt;/td&gt;
-&lt;/tr&gt;</pre>
-
-<h4 id="Altri_modi_di_usare_le_variabili_template">Altri modi di usare le variabili template</h4>
-
-<p>Utilizzando<code>\{{ form.as_table }}</code> come mostrato sopra, ogni campo viene renderizzato come riga di una tabella. Puoi anche renderizzare ogni campo come elemento di una lista (usando <code>\{{ form.as_ul }}</code> ) o come un paragrafo (<code>\{{ form.as_p }}</code>).</p>
-
-<p>È anche possibile avere il controllo completo sul rendering di ogni parte del form, indicizzando le sue proprietà mediante la notazione dei punti. Ad esempio, possiamo accedere a un numero di elementi separati per il nostro campo renewal_date:</p>
-
-<ul>
- <li><code>\{{ form.renewal_date }}:</code> L'intero campo.</li>
- <li><code>\{{ form.renewal_date.errors }}</code>: La lista degli errori.</li>
- <li><code>\{{ form.renewal_date.id_for_label }}</code>: L'id della label.</li>
- <li><code>\{{ form.renewal_date.help_text }}</code>: il testo di aiuto del campo.</li>
-</ul>
-
-<p>Per ulteriori esempi su come eseguire il rendering manuale dei form nei modelli e ciclare dinamicamente sui campi del modello, vedere <a href="https://docs.djangoproject.com/en/2.1/topics/forms/#rendering-fields-manually">Working with forms &gt; Rendering fields manually</a> (Django docs).</p>
-
-<h3 id="Testare_la_pagina">Testare la pagina</h3>
-
-<p>Se hai accettato la sfida proposta in <a href="/en-US/docs/Learn/Server-side/Django/authentication_and_sessions#Challenge_yourself">Django Tutorial Part 8: User authentication and permissions</a> dovresti avere una lista di libri in prestito nella libreria, che saranno visibili solamente allo staff. Possiamo aggiungere un link alla nostra pagina di rinnovo per ogni elemento utilizzando il codice template sotto.</p>
-
-<pre class="brush: html">{% if perms.catalog.can_mark_returned %}- &lt;a href="{% url 'renew-book-librarian' bookinst.id %}"&gt;Renew&lt;/a&gt; {% endif %}</pre>
-
-<div class="note">
-<p><strong>Note</strong>: Remember that your test login will need to have the permission "<code>catalog.can_mark_returned</code>" in order to access the renew book page (perhaps use your superuser account).</p>
-</div>
-
-<p>In alternativa, puoi costruire manualmente un URL di prova come questo: http://127.0.0.1:8000/catalog/book/&lt;bookinstance_id&gt;/renew/ (è possibile ottenere un id valido per le librerie navigando a una pagina dei dettagli del libro nella libreria, e copiare il campo id).</p>
-
-<h3 id="Come_appare">Come appare?</h3>
-
-<p>Se hai successo, il form di default sarà così:</p>
-
-<p><img alt="" src="https://mdn.mozillademos.org/files/14209/forms_example_renew_default.png" style="border-style: solid; border-width: 1px; display: block; height: 292px; margin: 0px auto; width: 680px;"></p>
-
-<p>The form with an invalid value entered will look like this:</p>
-
-<p><img alt="" src="https://mdn.mozillademos.org/files/14211/forms_example_renew_invalid.png" style="border-style: solid; border-width: 1px; display: block; height: 290px; margin: 0px auto; width: 658px;"></p>
-
-<p>The list of all books with renew links will look like this:</p>
-
-<p><img alt="" src="https://mdn.mozillademos.org/files/14207/forms_example_renew_allbooks.png" style="border-style: solid; border-width: 1px; display: block; height: 256px; margin: 0px auto; width: 613px;"></p>
-
-<h2 id="ModelForms">ModelForms</h2>
-
-<p>La creazione di una classe Form utilizzando l'approccio descritto sopra è molto flessibile, consente infatti di creare qualsiasi tipo di pagina di form che ti piace e associarla a qualsiasi modello o modello. Tuttavia, se hai solo bisogno di un modulo per mappare i campi di un singolo modello, il tuo modello definirà già la maggior parte delle informazioni necessarie nel tuo modulo: campi, etichette, testo della guida, ecc. Invece di ricreare le definizioni del modello nel tuo forma, è più facile usare la classe helper ModelForm per creare il modulo dal tuo modello. Questo ModelForm può quindi essere utilizzato all'interno delle visualizzazioni esattamente nello stesso modo di un modulo ordinario.</p>
-
-<p>Un modello di base <code>ModelForm</code> contenente gli stessi campi del nostro <code>RenewBookForm</code> è mostrato sotto. Tutto ciò che devi fare è aggiungere una classe <code>class Meta</code> con il modello associato (<code>BookInstance</code>) e un elenco dei campi del modello da includere nel modulo (è possibile includere tutti i campi utilizzando <code>fields = '__all__',</code> oppure è possibile utilizzare <code>exclude </code>(anziché i campi) per specificare i campi da non includere nel modello).</p>
-
-<pre class="brush: python">from django.forms import ModelForm
-
-from catalog.models import BookInstance
-
-class RenewBookModelForm(ModelForm):
-<strong> class Meta:
- model = BookInstance
- fields = ['due_back']</strong>
-</pre>
-
-<div class="note">
-<p><strong>Note</strong>: Questo potrebbe non sembrare tutto molto più semplice del semplice utilizzo di un modulo (e non è in questo caso, perché abbiamo solo un campo). Tuttavia, se hai molti campi, puoi ridurre la quantità di codice in modo abbastanza significativo!</p>
-</div>
-
-<p>Il resto delle informazioni proviene dalle definizioni del campo del modello (ad esempio etichette, widget, testo della guida, messaggi di errore). Se questi non sono corretti, possiamo sostituirli nella nostra classe Meta, specificando un dizionario contenente il campo da modificare e il suo nuovo valore. Ad esempio, in questo modulo potremmo volere un'etichetta per il nostro campo di "Data di rinnovo" (piuttosto che l'impostazione predefinita in base al nome del campo: "Due Back"), e vogliamo anche che il nostro testo di aiuto sia specifico per questo caso d'uso. La Meta sotto mostra come sovrascrivere questi campi, e puoi impostare allo stesso modo widget e messaggi_errore se i valori predefiniti non sono sufficienti.</p>
-
-<pre class="brush: python">class Meta:
- model = BookInstance
- fields = ['due_back']
-<strong> labels = {'due_back': _('New renewal date')}
- help_texts = {'due_back</strong><strong>': _('Enter a date between now and 4 weeks (default 3).')} </strong>
-</pre>
-
-<p>Per aggiungere la convalida è possibile utilizzare lo stesso approccio di un modulo normale: si definisce una funzione denominata <code>clean_field_name () </code>e si generano eccezioni <code>ValidationError </code>per valori non validi. L'unica differenza rispetto alla nostra forma originale è che il campo del modello è denominato <code>due_back </code>e non "<code>renewal_date</code>". Questa modifica è necessaria poiché il campo corrispondente in <code>BookInstance </code>è chiamato <code>due_back</code>.</p>
-
-<pre class="brush: python">from django.forms import ModelForm
-
-from catalog.models import BookInstance
-
-class RenewBookModelForm(ModelForm):
-<strong>    def clean_due_back(self):
-       data = self.cleaned_data['due_back</strong><strong>']
-
-  # Controlla se la data non è passata.
-       if data &lt; datetime.date.today():
-           raise ValidationError(_('Invalid date - renewal in past'))
-
-       <strong># Controlla se una data è nell'intervallo consentito (+4 settimane da oggi).</strong>
-       if data &gt; datetime.date.today() + datetime.timedelta(weeks=4):
-           raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead'))
-
-       # Ricorda di restituire sempre la data pulita.
-       return data
-</strong>
- class Meta:
- model = BookInstance
- fields = ['due_back']
- labels = {'due_back': _('Renewal date')}
- help_texts = {'due_back': _('Enter a date between now and 4 weeks (default 3).')}
-</pre>
-
-<p>La classe <code>RenewBookModelForm</code> <code>adesso funziona come la nostra originale RenewBookForm</code>. Puoi importarla e usarla ovunque attualmente usi  <code>RenewBookForm</code> a condizione che si aggiorni anche il nome della variabile corrispondente da  <code>renewal_date</code> a <code>due_back</code> come nella dichiarazione della seconda Form: <code>RenewBookModelForm(initial={'due_back': proposed_renewal_date}</code>.</p>
-
-<h2 id="Generic_editing_views">Generic editing views</h2>
-
-<p>The form handling algorithm we used in our function view example above represents an extremely common pattern in form editing views. Django abstracts much of this "boilerplate" for you, by creating <a href="https://docs.djangoproject.com/en/2.1/ref/class-based-views/generic-editing/">generic editing views</a> for creating, editing, and deleting views based on models. Not only do these handle the "view" behavior, but they automatically create the form class (a <code>ModelForm</code>) for you from the model.</p>
-
-<div class="note">
-<p><strong>Note: </strong>In addition to the editing views described here, there is also a <a href="https://docs.djangoproject.com/en/2.1/ref/class-based-views/generic-editing/#formview">FormView</a> class, which lies somewhere between our function view and the other generic views in terms of "flexibility" vs "coding effort". Using <code>FormView</code>, you still need to create your <code>Form</code>, but you don't have to implement all of the standard form-handling patterns. Instead, you just have to provide an implementation of the function that will be called once the submitted is known to be valid.</p>
-</div>
-
-<p>In this section we're going to use generic editing views to create pages to add functionality to create, edit, and delete <code>Author</code> records from our library — effectively providing a basic reimplementation of parts of the Admin site (this could be useful if you need to offer admin functionality in a more flexible way that can be provided by the admin site).</p>
-
-<h3 id="Views">Views</h3>
-
-<p>Open the views file (<strong>locallibrary/catalog/views.py</strong>) and append the following code block to the bottom of it:</p>
-
-<pre class="brush: python">from django.views.generic.edit import CreateView, UpdateView, DeleteView
-from django.urls import reverse_lazy
-
-from catalog.models import Author
-
-class AuthorCreate(CreateView):
- model = Author
- fields = '__all__'
- initial = {'date_of_death': '05/01/2018'}
-
-class AuthorUpdate(UpdateView):
- model = Author
- fields = ['first_name', 'last_name', 'date_of_birth', 'date_of_death']
-
-class AuthorDelete(DeleteView):
- model = Author
- success_url = reverse_lazy('authors')</pre>
-
-<p>As you can see, to create, update, or delete the views you need to derive from <code>CreateView</code>, <code>UpdateView</code>, and <code>DeleteView</code> (respectively) and then define the associated model.</p>
-
-<p>For the "create" and "update" cases you also need to specify the fields to display in the form (using the same syntax as for <code>ModelForm</code>). In this case, we show both the syntax to display "all" fields and how you can list them individually. You can also specify initial values for each of the fields using a dictionary of <em>field_name</em>/<em>value</em> pairs (here we arbitrarily set the date of death for demonstration purposes — you might want to remove that!). By default, these views will redirect on success to a page displaying the newly created/edited model item, which in our case will be the author detail view we created in a previous tutorial. You can specify an alternative redirect location by explicitly declaring parameter <code>success_url</code> (as done for the <code>AuthorDelete</code> class).</p>
-
-<p>The <code>AuthorDelete</code> class doesn't need to display any of the fields, so these don't need to be specified. You do however need to specify the <code>success_url</code>, because there is no obvious default value for Django to use. In this case, we use the <code><a href="https://docs.djangoproject.com/en/2.1/ref/urlresolvers/#reverse-lazy">reverse_lazy()</a></code> function to redirect to our author list after an author has been deleted — <code>reverse_lazy()</code> is a lazily executed version of <code>reverse()</code>, used here because we're providing a URL to a class-based view attribute.</p>
-
-<h3 id="Templates">Templates</h3>
-
-<p>The "create" and "update" views use the same template by default, which will be named after your model: <em>model_name</em><strong>_form.html</strong> (you can change the suffix to something other than <strong>_form</strong> using the <code>template_name_suffix</code> field in your view, e.g. <code>template_name_suffix = '_other_suffix'</code>)</p>
-
-<p>Create the template file <strong>locallibrary/catalog/templates/catalog/author_form.html</strong> and copy in the text below.</p>
-
-<pre class="brush: html">{% extends "base_generic.html" %}
-
-{% block content %}
- &lt;form action="" method="post"&gt;
- {% csrf_token %}
- &lt;table&gt;
- \{{ form.as_table }}
- &lt;/table&gt;
- &lt;input type="submit" value="Submit"&gt;
- &lt;/form&gt;
-{% endblock %}</pre>
-
-<p>This is similar to our previous forms and renders the fields using a table. Note also how again we declare the <code>{% csrf_token %}</code> to ensure that our forms are resistant to CSRF attacks.</p>
-
-<p>The "delete" view expects to find a template named with the format <em>model_name</em><strong>_confirm_delete.html</strong> (again, you can change the suffix using <code>template_name_suffix</code> in your view). Create the template file <strong>locallibrary/catalog/templates/catalog/author_confirm_delete</strong><strong>.html</strong> and copy in the text below.</p>
-
-<pre class="brush: html">{% extends "base_generic.html" %}
-
-{% block content %}
-
-&lt;h1&gt;Delete Author&lt;/h1&gt;
-
-&lt;p&gt;Are you sure you want to delete the author: \{{ author }}?&lt;/p&gt;
-
-&lt;form action="" method="POST"&gt;
- {% csrf_token %}
- &lt;input type="submit" value="Yes, delete."&gt;
-&lt;/form&gt;
-
-{% endblock %}
-</pre>
-
-<h3 id="URL_configurations">URL configurations</h3>
-
-<p>Open your URL configuration file (<strong>locallibrary/catalog/urls.py</strong>) and add the following configuration to the bottom of the file:</p>
-
-<pre class="brush: python">urlpatterns += [
-    path('author/create/', views.AuthorCreate.as_view(), name='author_create'),
-    path('author/&lt;int:pk&gt;/update/', views.AuthorUpdate.as_view(), name='author_update'),
-    path('author/&lt;int:pk&gt;/delete/', views.AuthorDelete.as_view(), name='author_delete'),
-]</pre>
-
-<p>There is nothing particularly new here! You can see that the views are classes, and must hence be called via <code>.as_view()</code>, and you should be able to recognize the URL patterns in each case. We must use <code>pk</code> as the name for our captured primary key value, as this is the parameter name expected by the view classes.</p>
-
-<p>The author create, update, and delete pages are now ready to test (we won't bother hooking them into the site sidebar in this case, although you can do so if you wish).</p>
-
-<div class="note">
-<p><strong>Note</strong>: Observant users will have noticed that we didn't do anything to prevent unauthorized users from accessing the pages! We leave that as an exercise for you (hint: you could use the <code>PermissionRequiredMixin</code> and either create a new permission or reuse our <code>can_mark_returned</code> permission).</p>
-</div>
-
-<h3 id="Testing_the_page">Testing the page</h3>
-
-<p>First, log in to the site with an account that has whatever permissions you decided are needed to access the author editing pages.</p>
-
-<p>Then navigate to the author create page: <a href="http://127.0.0.1:8000/catalog/author/create/">http://127.0.0.1:8000/catalog/author/create/</a>, which should look like the screenshot below.</p>
-
-<p><img alt="Form Example: Create Author" src="https://mdn.mozillademos.org/files/14223/forms_example_create_author.png" style="border-style: solid; border-width: 1px; display: block; height: 184px; margin: 0px auto; width: 645px;"></p>
-
-<p>Enter values for the fields and then press <strong>Submit</strong> to save the author record. You should now be taken to a detail view for your new author, with a URL of something like <em>http://127.0.0.1:8000/catalog/author/10</em>.</p>
-
-<p>You can test editing records by appending <em>/update/</em> to the end of the detail view URL (e.g. <em>http://127.0.0.1:8000/catalog/author/10/update/</em>) — we don't show a screenshot, because it looks just like the "create" page!</p>
-
-<p>Finally, we can delete the page by appending delete to the end of the author detail-view URL (e.g. <em>http://127.0.0.1:8000/catalog/author/10/delete/</em>). Django should display the delete page shown below. Press <strong>Yes, delete.</strong> to remove the record and be taken to the list of all authors.</p>
-
-<p><img alt="" src="https://mdn.mozillademos.org/files/14221/forms_example_delete_author.png" style="border-style: solid; border-width: 1px; display: block; height: 194px; margin: 0px auto; width: 561px;"></p>
-
-
-
-<h2 id="Challenge_yourself">Challenge yourself</h2>
-
-<p>Create some forms to create, edit, and delete <code>Book</code> records. You can use exactly the same structure as for <code>Authors</code>. If your <strong>book_form.html</strong> template is just a copy-renamed version of the <strong>author_form.html</strong> template, then the new "create book" page will look like the screenshot below:</p>
-
-<p><img alt="" src="https://mdn.mozillademos.org/files/14225/forms_example_create_book.png" style="border-style: solid; border-width: 1px; display: block; height: 521px; margin: 0px auto; width: 595px;"></p>
-
-<ul>
-</ul>
-
-<h2 id="Summary">Summary</h2>
-
-<p>Creating and handling forms can be a complicated process! Django makes it much easier by providing programmatic mechanisms to declare, render, and validate forms. Furthermore, Django provides generic form editing views that can do <em>almost all</em> the work to define pages that can create, edit, and delete records associated with a single model instance.</p>
-
-<p>There is a lot more that can be done with forms (check out our See also list below), but you should now understand how to add basic forms and form-handling code to your own websites.</p>
-
-<h2 id="See_also">See also</h2>
-
-<ul>
- <li><a href="https://docs.djangoproject.com/en/2.1/topics/forms/">Working with forms</a> (Django docs)</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/intro/tutorial04/#write-a-simple-form">Writing your first Django app, part 4 &gt; Writing a simple form</a> (Django docs)</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/api/">The Forms API</a> (Django docs)</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/">Form fields</a> (Django docs) </li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/validation/">Form and field validation</a> (Django docs)</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-editing/">Form handling with class-based views</a> (Django docs)</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/topics/forms/modelforms/">Creating forms from models</a> (Django docs)</li>
- <li><a href="https://docs.djangoproject.com/en/2.1/ref/class-based-views/generic-editing/">Generic editing views</a> (Django docs)</li>
-</ul>
-
-<p>{{PreviousMenuNext("Learn/Server-side/Django/authentication_and_sessions", "Learn/Server-side/Django/Testing", "Learn/Server-side/Django")}}</p>
-
-
-
-<h2 id="In_this_module">In this module</h2>
-
-<ul>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Introduction">Django introduction</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Setting up a Django development environment</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Django Tutorial: The Local Library website</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Django Tutorial Part 2: Creating a skeleton website</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Models">Django Tutorial Part 3: Using models</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django Tutorial Part 4: Django admin site</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Tutorial Part 5: Creating our home page</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Tutorial Part 6: Generic list and detail views</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Tutorial Part 7: Sessions framework</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Authentication">Django Tutorial Part 8: User authentication and permissions</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Tutorial Part 9: Working with forms</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Testing">Django Tutorial Part 10: Testing a Django web application</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Django Tutorial Part 11: Deploying Django to production</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/web_application_security">Django web application security</a></li>
- <li><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li>
-</ul>