{"title":"Scrivere la tua prima applicazione in Django, parte 4","version":"4.2","locale":"it","docname":"intro/tutorial04","url":"/it/4.2/intro/tutorial04/","canonical":"https://djangodocs.dev/it/4.2/intro/tutorial04/","summary":"Questo tutorial inizia dove si è interrotto il tutorial Tutorial 3. Continuiamo con l’applicazione web dei questionari e ci focalizzeremo sul processamento…","html":"<h1>Scrivere la tua prima applicazione in Django, parte 4<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-4\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Questo tutorial inizia dove si è interrotto il tutorial <a class=\"reference internal\" href=\"/it/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>. Continuiamo con l’applicazione web dei questionari e ci focalizzeremo sul processamento dei form e sul ridurre il nostro codice.</p>\n<aside class=\"admonition-where-to-get-help admonition\" role=\"note\">\n<p class=\"admonition-title\">Dove trovare aiuto:</p>\n<p>Se hai difficoltà a completare questo tutorial,  per favore vai alla sezione <a class=\"reference internal\" href=\"/it/4.2/faq/help/\"><span class=\"doc\">Getting Help</span></a> delle FAQ.</p>\n</aside>\n<section id=\"write-a-minimal-form\">\n<h2>Scrivere un modulo minimale<a class=\"heading-anchor\" href=\"#write-a-minimal-form\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Aggiorniamo il nostro template per i dettagli del questionario («polls/detail.html») dall’ultimo tutorial, così che il template contenga un elemento HTML <code class=\"docutils literal notranslate\">&lt;form&gt;</code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/templates/polls/detail.html</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">form</span> <span class=\"na\">action</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;polls:vote&#39;</span> <span class=\"nv\">question.id</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span> <span class=\"na\">method</span><span class=\"o\">=</span><span class=\"s\">&quot;post&quot;</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">csrf_token</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">fieldset</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">legend</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">h1</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">h1</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">legend</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">error_message</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">strong</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">error_message</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">strong</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">choice</span> <span class=\"k\">in</span> <span class=\"nv\">question.choice_set.all</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">input</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;radio&quot;</span> <span class=\"na\">name</span><span class=\"o\">=</span><span class=\"s\">&quot;choice&quot;</span> <span class=\"na\">id</span><span class=\"o\">=</span><span class=\"s\">&quot;choice</span><span class=\"cp\">{{</span> <span class=\"nb\">forloop</span><span class=\"nv\">.counter</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span> <span class=\"na\">value</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">choice.id</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">label</span> <span class=\"na\">for</span><span class=\"o\">=</span><span class=\"s\">&quot;choice</span><span class=\"cp\">{{</span> <span class=\"nb\">forloop</span><span class=\"nv\">.counter</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">choice.choice_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">label</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">br</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">fieldset</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">input</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;submit&quot;</span> <span class=\"na\">value</span><span class=\"o\">=</span><span class=\"s\">&quot;Vote&quot;</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">form</span><span class=\"p\">&gt;</span>\n</code></pre></figure>\n<p>Una rapida carrellata:</p>\n<ul class=\"simple\">\n<li><p>Il template di cui sopra mostra un radio button per ogni scelta del sondaggio. Il <code class=\"docutils literal notranslate\">valore</code> di ogni radio button è l’ID associato alla scelta. Il <code class=\"docutils literal notranslate\">nome</code> di ogni radio button è <code class=\"docutils literal notranslate\">&quot;choice&quot;</code>. Questo significa che quando qualcuno seleziona uno dei radio button ed invia il form, manderà il dato <code class=\"docutils literal notranslate\">choice=#</code> in POST, dove # è l’ID della scelta selezionata. Questo è il concetto alla base dei form HTML.</p></li>\n<li><p>Impostiamo la <code class=\"docutils literal notranslate\">action</code> del form a <code class=\"docutils literal notranslate\">{% url 'polls:vote' question.id %}</code> ed impostiamo <code class=\"docutils literal notranslate\">method=&quot;post&quot;</code>. Usare <code class=\"docutils literal notranslate\">method=&quot;post&quot;</code> (in opposizione a <code class=\"docutils literal notranslate\">method=&quot;get&quot;</code>) è molto importante perchè il submit di questo form altererà i dati a lato server. Tutte le volte che crei un form che altera i dati a lato server, usa <code class=\"docutils literal notranslate\">method=&quot;post&quot;</code>. Questo consiglio non si applica solo a Django; è una buona pratica di sviluppo web, in generale.</p></li>\n<li><p><code class=\"docutils literal notranslate\">forloop.counter</code> indica quante volte il tag <a class=\"reference internal\" href=\"/it/4.2/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\">for</code></a> ha attraversato suo loop</p></li>\n<li><p>Siccome stiamo creando un form POST (che può avere l’effetto di modificare i dati), dobbiamo preoccuparci delle Cross Site Request Forgeries. Per fortuna, non ce ne dobbiamo preoccupare troppo, perchè Django ci offre un sistema che ci aiuta molto a proteggerci. In breve, tutti i form POST che sono indirizzati dalle url interne devono usare il tag <a class=\"reference internal\" href=\"/it/4.2/ref/templates/builtins/#std-templatetag-csrf_token\"><code class=\"xref std std-ttag docutils literal notranslate\">{% csrf_token %}</code></a>.</p></li>\n</ul>\n<p>Adesso, creiamo una view Django che gestisce i dati in submit e ci fa qualcosa. Ricorda che nel <a class=\"reference internal\" href=\"/it/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>, abbiamo creato una URLconf per l’applicazione sondaggio che include questa linea:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/urls.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code>path<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:question_id&gt;/vote/&quot;</span><span class=\"p\">,</span> views<span class=\"o\">.</span>vote<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;vote&quot;</span><span class=\"p\">),</span>\n</code></pre></figure>\n<p>Abbiamo anche creato una implementazione dummy della funzione <code class=\"docutils literal notranslate\">vote()</code>. Creiamone una versione reali. Aggiungi quanto di seguito a <code class=\"docutils literal notranslate\">polls/views.py</code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/views.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse<span class=\"p\">,</span> HttpResponseRedirect\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> get_object_or_404<span class=\"p\">,</span> render\n<span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> reverse\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Choice<span class=\"p\">,</span> Question\n\n\n<span class=\"c1\"># ...</span>\n<span class=\"k\">def</span> <span class=\"nf\">vote</span><span class=\"p\">(</span>request<span class=\"p\">,</span> question_id<span class=\"p\">):</span>\n    question <span class=\"o\">=</span> get_object_or_404<span class=\"p\">(</span>Question<span class=\"p\">,</span> pk<span class=\"o\">=</span>question_id<span class=\"p\">)</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        selected_choice <span class=\"o\">=</span> question<span class=\"o\">.</span>choice_set<span class=\"o\">.</span>get<span class=\"p\">(</span>pk<span class=\"o\">=</span>request<span class=\"o\">.</span>POST<span class=\"p\">[</span><span class=\"s2\">&quot;choice&quot;</span><span class=\"p\">])</span>\n    <span class=\"k\">except</span> <span class=\"p\">(</span><span class=\"ne\">KeyError</span><span class=\"p\">,</span> Choice<span class=\"o\">.</span>DoesNotExist<span class=\"p\">):</span>\n        <span class=\"c1\"># Redisplay the question voting form.</span>\n        <span class=\"k\">return</span> render<span class=\"p\">(</span>\n            request<span class=\"p\">,</span>\n            <span class=\"s2\">&quot;polls/detail.html&quot;</span><span class=\"p\">,</span>\n            <span class=\"p\">{</span>\n                <span class=\"s2\">&quot;question&quot;</span><span class=\"p\">:</span> question<span class=\"p\">,</span>\n                <span class=\"s2\">&quot;error_message&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;You didn&#39;t select a choice.&quot;</span><span class=\"p\">,</span>\n            <span class=\"p\">},</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        selected_choice<span class=\"o\">.</span>votes <span class=\"o\">+=</span> <span class=\"mi\">1</span>\n        selected_choice<span class=\"o\">.</span>save<span class=\"p\">()</span>\n        <span class=\"c1\"># Always return an HttpResponseRedirect after successfully dealing</span>\n        <span class=\"c1\"># with POST data. This prevents data from being posted twice if a</span>\n        <span class=\"c1\"># user hits the Back button.</span>\n        <span class=\"k\">return</span> HttpResponseRedirect<span class=\"p\">(</span>reverse<span class=\"p\">(</span><span class=\"s2\">&quot;polls:results&quot;</span><span class=\"p\">,</span> args<span class=\"o\">=</span><span class=\"p\">(</span>question<span class=\"o\">.</span>id<span class=\"p\">,)))</span>\n</code></pre></figure>\n<p>Questo codice comprende alcuni aspetti non ancora trattati in questo tutorial:</p>\n<ul>\n<li><p><a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpRequest.POST\" title=\"django.http.HttpRequest.POST\"><code class=\"xref py py-attr docutils literal notranslate\">request.POST</code></a> è un oggetto simil-dizionario che ti lascia accedere ai dati in submit per nome di chiave. In questo caso, <code class=\"docutils literal notranslate\">request.POST['choice']</code> restituisce l’ID della scelta selezionata, come stringa. I valori <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpRequest.POST\" title=\"django.http.HttpRequest.POST\"><code class=\"xref py py-attr docutils literal notranslate\">request.POST</code></a> sono sempre stringhe.</p>\n<p>Nota che Django ti offre anche <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpRequest.GET\" title=\"django.http.HttpRequest.GET\"><code class=\"xref py py-attr docutils literal notranslate\">request.GET</code></a> per accedere ai dati in GET allo stesso modo – ma stiamo esplicitamente usando <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpRequest.POST\" title=\"django.http.HttpRequest.POST\"><code class=\"xref py py-attr docutils literal notranslate\">request.POST</code></a> nel nostro codice, per assicurarci che i dati vengano alterati solo con una chiamata POST.</p>\n</li>\n<li><p><code class=\"docutils literal notranslate\">request.POST['choice']</code> solleverà <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#KeyError\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\">KeyError</code></a> se <code class=\"docutils literal notranslate\">choice</code> non è presente tra i dati in POST. Il codice sopra controlla <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#KeyError\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\">KeyError</code></a> e mostra di nuovo il form della domanda con un messaggio di errore se <code class=\"docutils literal notranslate\">choice</code> non viene fornita.</p></li>\n<li><p>Dopo aver incrementato il conteggio delle scelte, il codice restituisce una <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponseRedirect</code></a> piuttosto che una normale <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponse</code></a>. <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponseRedirect</code></a> prende un solo argomento: la URL alla quale l’utente sarà redirezionato (vedi il punto seguente per sapere come costruiamo la URL in questo caso).</p>\n<p>Come il commento Python qui sopra fa notare, dovresti sempre restituire un <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponseRedirect</code></a> dopo aver avuto a che fare con successo con dati in POST. Questo consiglio non riguarda nello specifico solo Django; è una buona pratica per lo sviluppo web, in generale.</p>\n</li>\n<li><p>In questo esempio stiamo usando la funzione <a class=\"reference internal\" href=\"/it/4.2/ref/urlresolvers/#django.urls.reverse\" title=\"django.urls.reverse\"><code class=\"xref py py-func docutils literal notranslate\">reverse()</code></a> nel costruttore <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponseRedirect</code></a>. Questa funzione aiuta ad evitare di dover codificare la URL nella funzione view. E” dato il nome della view a cui vogliamo passare il controllo e la porzione della URL relativa alla variabile che punta alla URL. In questo caso, usando la URLconf che abbiamo impostato nel <a class=\"reference internal\" href=\"/it/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>, questa chiamata <a class=\"reference internal\" href=\"/it/4.2/ref/urlresolvers/#django.urls.reverse\" title=\"django.urls.reverse\"><code class=\"xref py py-func docutils literal notranslate\">reverse()</code></a> restituirà una stringa come:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"s2\">&quot;/polls/3/results/&quot;</span>\n</code></pre></div>\n<p>dove il <code class=\"docutils literal notranslate\">3</code> è il valore di <code class=\"docutils literal notranslate\">question.id</code>. Questa URL redirezionata poi chiamerà la view <code class=\"docutils literal notranslate\">'results'</code> per mostrare la pagina finale.</p>\n</li>\n</ul>\n<p>Come menzionato in <a class=\"reference internal\" href=\"/it/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>, <code class=\"docutils literal notranslate\">request</code> è un oggetto <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\">HttpRequest</code></a>. Per saperne di più sugli oggetti <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\">HttpRequest</code></a>, vedi la <a class=\"reference internal\" href=\"/it/4.2/ref/request-response/\"><span class=\"doc\">documentazione su request e response</span></a>.</p>\n<p>Dopo che qualcuno ha votato una domanda, la vista <code class=\"docutils literal notranslate\">vote()</code> reindirizza alla pagina dei risultati per la domanda. Scriviamo quella vista:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/views.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> get_object_or_404<span class=\"p\">,</span> render\n\n\n<span class=\"k\">def</span> <span class=\"nf\">results</span><span class=\"p\">(</span>request<span class=\"p\">,</span> question_id<span class=\"p\">):</span>\n    question <span class=\"o\">=</span> get_object_or_404<span class=\"p\">(</span>Question<span class=\"p\">,</span> pk<span class=\"o\">=</span>question_id<span class=\"p\">)</span>\n    <span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"s2\">&quot;polls/results.html&quot;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;question&quot;</span><span class=\"p\">:</span> question<span class=\"p\">})</span>\n</code></pre></figure>\n<p>Questa è praticamente la stessa view di <code class=\"docutils literal notranslate\">detail()</code> dal <a class=\"reference internal\" href=\"/it/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>. L’unica differenza è il nome di template. Metteremo a posto questa ridondanza più tardi.</p>\n<p>Ora, crea un template <code class=\"docutils literal notranslate\">polls/results.html</code>  :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/templates/polls/results.html</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">h1</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">h1</span><span class=\"p\">&gt;</span>\n\n<span class=\"p\">&lt;</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">choice</span> <span class=\"k\">in</span> <span class=\"nv\">question.choice_set.all</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">choice.choice_text</span> <span class=\"cp\">}}</span> -- <span class=\"cp\">{{</span> <span class=\"nv\">choice.votes</span> <span class=\"cp\">}}</span> vote<span class=\"cp\">{{</span> <span class=\"nv\">choice.votes</span><span class=\"o\">|</span><span class=\"nf\">pluralize</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n\n<span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;polls:detail&#39;</span> <span class=\"nv\">question.id</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>Vote again?<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n</code></pre></figure>\n<p>Adesso, vai su <code class=\"docutils literal notranslate\">/polls/1/</code> nel browser e vota il sondaggio. Dovresti vedere la pagina dei risultati che si aggiorna ogni volta che voti. Se invii il form senza scegliere una risposta, dovresti vedere il messaggio di errore.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Nota</p>\n<p>Il codice per la view <code class=\"docutils literal notranslate\">vote()</code> ha un piccolo problema. Prende prende l’oggetto <code class=\"docutils literal notranslate\">selected_choice</code> dal db, poi li risalva nel database. Se due utenti del sito cercano di votare <em>esattamente</em> allo stesso momento, qualcosa potrebbe andare storto: lo stesso valore, diciamo 42, verrebbe ritirato per <code class=\"docutils literal notranslate\">votes</code>. Poi, per entrambi gli utenti verrebbe calcolato il valore 43 e salvato ma 44 sarebbe il valore giusto.</p>\n<p>Questa viene chiamata <em>race condition</em>. Se sei interessato, puoi leggere <a class=\"reference internal\" href=\"/it/4.2/ref/models/expressions/#avoiding-race-conditions-using-f\"><span class=\"std std-ref\">Avoiding race conditions using F()</span></a> per sapere come risolvere questo problema.</p>\n</aside>\n</section>\n<section id=\"use-generic-views-less-code-is-better\">\n<h2>Usa viste generiche: meno codice è meglio<a class=\"heading-anchor\" href=\"#use-generic-views-less-code-is-better\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Le view <code class=\"docutils literal notranslate\">detail()</code> (dal <a class=\"reference internal\" href=\"/it/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>) e <code class=\"docutils literal notranslate\">results()</code> sono molto brevi – e, come menzionato sopra, ridondanti. La view <code class=\"docutils literal notranslate\">index()</code>, che mostra una lista di sondaggi, è simile.</p>\n<p>Queste views rappresentano un caso comune di sviluppo web di base; prendere dei dati dal database in accordo con un parametro passato via URL, caricare un template e restituire il template per il rendering.\nDal momento che questo è molto comune, Django fornisce una scorciatoia, chiamata sistema «generic views».</p>\n<p>Generic views abstract common patterns to the point where you don’t even need to\nwrite Python code to write an app. For example, the\n<a class=\"reference internal\" href=\"/it/4.2/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\">ListView</code></a> and\n<a class=\"reference internal\" href=\"/it/4.2/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\">DetailView</code></a> generic views\nabstract the concepts of «display a list of objects» and\n«display a detail page for a particular type of object» respectively.</p>\n<p>Convertiamo la nostra app dei sondaggi affinchè utilizzi il sistema delle view generiche, in modo da poter cancellare un sacco di codice. Dovremo fare la conversione in qualche step.</p>\n<ol class=\"arabic simple\">\n<li><p>Converti la URLconf.</p></li>\n<li><p>Cancella alcune delle vecchie, non necessarie viste.</p></li>\n<li><p>Introduci nuove visualizzazioni basate sulle generic views di Django.</p></li>\n</ol>\n<p>Continua a leggere per i dettagli.</p>\n<aside class=\"admonition-why-the-code-shuffle admonition\" role=\"note\">\n<p class=\"admonition-title\">Perchè il code-shuffle?</p>\n<p>Solitamente, quando scrivi un’applicazione in Django, dovresti valutare quali viste generiche vanno bene per il tuo problema, invece di ristrutturare il codice a metà strada Ma questa guida era intenzionalmente focalizzato fino ad ora, sullo scrivere le viste nel modo più difficile, per mettere a punto i concetti principali.</p>\n<p>Dovresti conoscere la matematica di base prima di iniziare a usare una calcolatrice.</p>\n</aside>\n<section id=\"amend-urlconf\">\n<h3>Correggere la URLconf<a class=\"heading-anchor\" href=\"#amend-urlconf\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Prima di tutto, apri la URLconf <code class=\"docutils literal notranslate\">polls/urls.py</code> e cambiala così:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/urls.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> path\n\n<span class=\"kn\">from</span> <span class=\"nn\">.</span> <span class=\"kn\">import</span> views\n\napp_name <span class=\"o\">=</span> <span class=\"s2\">&quot;polls&quot;</span>\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;&quot;</span><span class=\"p\">,</span> views<span class=\"o\">.</span>IndexView<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;index&quot;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:pk&gt;/&quot;</span><span class=\"p\">,</span> views<span class=\"o\">.</span>DetailView<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;detail&quot;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:pk&gt;/results/&quot;</span><span class=\"p\">,</span> views<span class=\"o\">.</span>ResultsView<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;results&quot;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:question_id&gt;/vote/&quot;</span><span class=\"p\">,</span> views<span class=\"o\">.</span>vote<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;vote&quot;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>Note that the name of the matched pattern in the path strings of the second and\nthird patterns has changed from <code class=\"docutils literal notranslate\">&lt;question_id&gt;</code> to <code class=\"docutils literal notranslate\">&lt;pk&gt;</code>. This is\nnecessary because we’ll use the\n<a class=\"reference internal\" href=\"/it/4.2/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\">DetailView</code></a> generic view to replace our\n<code class=\"docutils literal notranslate\">detail()</code> and <code class=\"docutils literal notranslate\">results()</code> views, and it expects the primary key value\ncaptured from the URL to be called <code class=\"docutils literal notranslate\">&quot;pk&quot;</code>.</p>\n</section>\n<section id=\"amend-views\">\n<h3>Correggere le viste<a class=\"heading-anchor\" href=\"#amend-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Poi, andremo a rimuovere le nostre vecchie view <code class=\"docutils literal notranslate\">index</code>, <code class=\"docutils literal notranslate\">detail</code> e <code class=\"docutils literal notranslate\">results</code> per usare le view generiche di Django. Per farlo, apri il file <code class=\"docutils literal notranslate\">polls/views.py</code> e cambialo così:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/views.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponseRedirect\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> get_object_or_404<span class=\"p\">,</span> render\n<span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> reverse\n<span class=\"kn\">from</span> <span class=\"nn\">django.views</span> <span class=\"kn\">import</span> generic\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Choice<span class=\"p\">,</span> Question\n\n\n<span class=\"k\">class</span> <span class=\"nc\">IndexView</span><span class=\"p\">(</span>generic<span class=\"o\">.</span>ListView<span class=\"p\">):</span>\n    template_name <span class=\"o\">=</span> <span class=\"s2\">&quot;polls/index.html&quot;</span>\n    context_object_name <span class=\"o\">=</span> <span class=\"s2\">&quot;latest_question_list&quot;</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">get_queryset</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"sd\">&quot;&quot;&quot;Return the last five published questions.&quot;&quot;&quot;</span>\n        <span class=\"k\">return</span> Question<span class=\"o\">.</span>objects<span class=\"o\">.</span>order_by<span class=\"p\">(</span><span class=\"s2\">&quot;-pub_date&quot;</span><span class=\"p\">)[:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">DetailView</span><span class=\"p\">(</span>generic<span class=\"o\">.</span>DetailView<span class=\"p\">):</span>\n    model <span class=\"o\">=</span> Question\n    template_name <span class=\"o\">=</span> <span class=\"s2\">&quot;polls/detail.html&quot;</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">ResultsView</span><span class=\"p\">(</span>generic<span class=\"o\">.</span>DetailView<span class=\"p\">):</span>\n    model <span class=\"o\">=</span> Question\n    template_name <span class=\"o\">=</span> <span class=\"s2\">&quot;polls/results.html&quot;</span>\n\n\n<span class=\"k\">def</span> <span class=\"nf\">vote</span><span class=\"p\">(</span>request<span class=\"p\">,</span> question_id<span class=\"p\">):</span>\n    <span class=\"o\">...</span>  <span class=\"c1\"># same as above, no changes needed.</span>\n</code></pre></figure>\n<p>Each generic view needs to know what model it will be acting upon. This is\nprovided using either the <code class=\"docutils literal notranslate\">model</code> attribute (in this example, <code class=\"docutils literal notranslate\">model =\nQuestion</code> for  <code class=\"docutils literal notranslate\">DetailView</code> and <code class=\"docutils literal notranslate\">ResultsView</code>) or by defining the\n<a class=\"reference internal\" href=\"/it/4.2/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.get_queryset\" title=\"django.views.generic.list.MultipleObjectMixin.get_queryset\"><code class=\"xref py py-meth docutils literal notranslate\">get_queryset()</code></a> method (as\nshown in <code class=\"docutils literal notranslate\">IndexView</code>).</p>\n<p>Di default, la view generica  <a class=\"reference internal\" href=\"/it/4.2/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\">DetailView</code></a> usa un template chiamato &lt;app name&gt;/&lt;model name&gt;_detail.html`. Nel nostro caso, dovrebbe usare il template <code class=\"docutils literal notranslate\">&quot;polls/question_detail.html&quot;</code>. L’attributo <code class=\"docutils literal notranslate\">template_name</code> è utile per usare un template specifico invece del nome di template generato automaticamente. Specifichiamo anche il <code class=\"docutils literal notranslate\">template_name</code> per la list view <code class=\"docutils literal notranslate\">results</code> – questo ci assicura che la view dei risultati e la view dei dettagli abbiamo una interfaccia diversa quando vengono mostrate, anche se, dietro le quinte, sono entrambe <a class=\"reference internal\" href=\"/it/4.2/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\">DetailView</code></a>.</p>\n<p>In modo simile, la view generica <a class=\"reference internal\" href=\"/it/4.2/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\">ListView</code></a> usa un template di default chiamato <code class=\"docutils literal notranslate\">&lt;app name&gt;/&lt;model name&gt;_list.html</code>; usiamo <code class=\"docutils literal notranslate\">template_name</code> per dire a <a class=\"reference internal\" href=\"/it/4.2/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\">ListView</code></a> di usare il nostro template esistente <code class=\"docutils literal notranslate\">&quot;polls/index.html&quot;</code>.</p>\n<p>Nella parte precedente di questo tutorial, i template sono stati forniti con un contesto che contiene le variabili <code class=\"docutils literal notranslate\">question</code> e <code class=\"docutils literal notranslate\">latest_question_list</code>. Per <code class=\"docutils literal notranslate\">DetailView</code> la variabile <code class=\"docutils literal notranslate\">question</code> viene fornita automaticamente – visto che stiamo usando un modello Django (<code class=\"docutils literal notranslate\">Question</code>), Django è in grado di determinare un nome appropriato per la variabile di contesto. Comunque, per ListView, la variabile di contesto generata automaticamente è <code class=\"docutils literal notranslate\">question_list</code>. Per sovrascrivere questo, forniamo l’attributo context_object_name`, specificando che vogliamo usare <code class=\"docutils literal notranslate\">latest_question_list</code> al suo posto. Come approccio alternativo, puoi cambiare i tuoi template per rispecchiare le nuove variabili di contesto di default – ma è molto più facile dire a Django di usare le variabili che vuoi.</p>\n<p>Esegui il server e usa la tua nuova applicazione di sondaggio basata su visualizzazioni generiche.</p>\n<p>Per i dettagli completi sulle viste generiche, vedere la: doc:generic views documentation &lt;/topics/class-based-views/index&gt;.</p>\n<p>Quando hai dimestichezza con i moduli e le visualizzazioni generiche, leggi la <a class=\"reference internal\" href=\"/it/4.2/intro/tutorial05/\"><span class=\"doc\">parte 5 di questo tutorial</span></a> per scoprire come testare la nostra app per i sondaggi.</p>\n</section>\n</section>","rootId":"writing-your-first-django-app-part-4","toc":[{"title":"Scrivere un modulo minimale","anchor":"write-a-minimal-form","children":[]},{"title":"Usa viste generiche: meno codice è meglio","anchor":"use-generic-views-less-code-is-better","children":[{"title":"Correggere la URLconf","anchor":"amend-urlconf","children":[]},{"title":"Correggere le viste","anchor":"amend-views","children":[]}]}],"breadcrumbs":[{"docname":"intro/index","title":"Come iniziare","url":"/it/4.2/intro/"}],"prev":{"docname":"intro/tutorial03","title":"Scrivere la tua prima applicazione in Django, parte 3","url":"/it/4.2/intro/tutorial03/"},"next":{"docname":"intro/tutorial05","title":"Scrivere la tua prima applicazione in Django, parte 5","url":"/it/4.2/intro/tutorial05/"},"formats":{"html":"/it/4.2/intro/tutorial04/","markdown":"/it/4.2/intro/tutorial04.md","json":"/it/4.2/intro/tutorial04.json"},"source":"https://github.com/django/django/blob/stable/4.2.x/docs/intro/tutorial04.txt","official":"https://docs.djangoproject.com/it/4.2/intro/tutorial04/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}