---
title: "Scrivere la tua prima applicazione in Django, parte 7"
version: 6.0
locale: it
source: https://docs.djangoproject.com/it/6.0/intro/tutorial07/
canonical: https://djangodocs.dev/it/6.0/intro/tutorial07/
---
# Scrivere la tua prima applicazione in Django, parte 7

Questo tutorial inizia dove si è interrotto [Tutorial 6](/it/6.0/intro/tutorial06/). Stiamo proseguendo con l’applicazione web per i questionari e ci concentreremo sul sito generato automaticamente per l’amministrazione di Django che abbiamo esplorato in prima battuta nel [Tutorial 2](/it/6.0/intro/tutorial02/).

> **Dove trovare aiuto:**
>
> Se hai difficoltà a completare questo tutorial,  per favore vai alla sezione [Getting Help](/it/6.0/faq/help/) delle FAQ.

## Personalizzare il modulo di amministrazione

Registrando il modello `Question` con `admin.site.register(Question)`, Django è stato in grado di costruire un form di default. Spesso, vorrai personalizzare il modo in cui il form di amministrazione appare e funziona. Lo farai dicendo a Django quali opzioni vuoi quando registrerai l’oggetto.

Vediamo come funziona riordinando i campi nel modulo di modifica. Sostituisci la riga `admin.site.register(Question)` con:

*`polls/admin.py`*

```python
from django.contrib import admin

from .models import Question

class QuestionAdmin(admin.ModelAdmin):
    fields = ["pub_date", "question_text"]

admin.site.register(Question, QuestionAdmin)
```

Seguirai questo pattern – crea una classe del modello di amministrazione, poi passala come secondo argomento a  `admin.site.register()` – ogni volta che vuoi cambiare le opzioni nel panello di amministrazione del modello.

Questa particolare modifica qui sopra fa sì che la «Data di pubblicazione» venga prima del campo «Domanda»:

![I campi sono stati riordinati](intro/_images/admin07.png)

Questo non è impressionante con solo due campi, ma per i moduli di amministrazione con dozzine di campi, la scelta di un ordine intuitivo è un dettaglio importante per l’usabilità.

E parlando di moduli con dozzine di campi, potresti voler dividere il modulo in gruppi di campi:

*`polls/admin.py`*

```python
from django.contrib import admin

from .models import Question

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {"fields": ["question_text"]}),
        ("Date information", {"fields": ["pub_date"]}),
    ]

admin.site.register(Question, QuestionAdmin)
```

Il primo elemento di ogni tupla in [`fieldsets`](/it/6.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets) è il titolo del fieldset. Ecco come il nostro form appare adesso:

![I form ora hanno i fieldset](intro/_images/admin08t.png)

## Aggiunta di oggetti correlati

OK, abbiamo la nostra pagina di amministrazione del modello Question, ma una  `Question` ha più `Choice`, e il pannello di amministrazione non mostra le scelte.

Ancora.

Esistono due modi per risolvere questo problema. Il primo è registrare `Scelta` nell’amministrazione proprio come abbiamo fatto con `Domanda`:

*`polls/admin.py`*

```python
from django.contrib import admin

from .models import Choice, Question

# ...
admin.site.register(Choice)
```

Ora «Scelte» è un’opzione disponibile nell’amministrazione di Django. Il modulo «Aggiungi scelta» ha questo aspetto:

![Pagina di amministrazione per le scelte](intro/_images/admin09.png)

In quel form, il campo «Question» è un menu a tendina contenente tutte le domande nel database. Django sa che una [`ForeignKey`](/it/6.0/ref/models/fields/#django.db.models.ForeignKey) dovrebbe essere rappresentata nell’admin come una `<select>`. Nel nostro caso, esiste solo una domanda a questo punto.

Also note the «Add another question» button (displayed as a plus sign) to the
right of the «Question» field. Every `ForeignKey` relationship gets this
button for free. When you click this button, you’ll get a popup window with the
«Add question» form. If you add a question in that window and click «Save»,
Django will save the question to the database and dynamically add it as the
selected choice on the «Add choice» form you’re looking at.

Ma, onestamente, questo è un modo inefficiente di aggiungere oggetti `Choice` al sistema. Sarebbe meglio se potessi aggiungere un gruppo di Choices direttamente quando crei l’oggetto `Question`. Facciamolo.

Rimuovere la chiamata `register()` per il modello `Scelta`. Quindi, modifica il codice di registrazione `Domanda` per leggere:

*`polls/admin.py`*

```python
from django.contrib import admin

from .models import Choice, Question

class ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {"fields": ["question_text"]}),
        ("Date information", {"fields": ["pub_date"], "classes": ["collapse"]}),
    ]
    inlines = [ChoiceInline]

admin.site.register(Question, QuestionAdmin)
```

Questo dice a Django: gli oggetti «`Choice` sono modificati nella pagina di amministrazione del modello `Question`. Di default, fornisce abbastanza campi per 3 scelte.

Carica la pagina «Aggiungi domanda» per vedere come appare:

![La pagina di aggiunta di una domanda ora contiene le scelte](intro/_images/admin10t.png)

Funziona in questo modo: Ci sono tre slot per le relative Choices – come specificato dall” `extra` – e ogni volta torni alla pagina «Change» per un oggetto che è stato già creato, tu vedi altri ricevi slot.

At the end of the three current slots you will find an «Add another Choice»
link. If you click on it, a new slot will be added. If you want to remove the
added slot, you can click on the X to the top right of the added slot. This
image shows an added slot:

![Slot aggiuntivo aggiunto dinamicamente](intro/_images/admin14t.png)

Un piccolo problema. Occupa molto spazio dello schermo mostrare tutti i campi per inserire i relativi oggetti `Choice`. Per questo motivo, Django offre un modo tabellare per mostrare i relativi oggetti inline. Per usarlo, cambia la dichiarazione `ChoiceInline` per leggere:

*`polls/admin.py`*

```python
class ChoiceInline(admin.TabularInline): ...
```

Con questa  `TabularInline` (invece di `StackedInline`), gli oggetti relativi vengono mostrati in un modo più compatto, in un formato tabellare:

![La pagina per l'aggiunta di una domanda ora ha scelte più compatte](intro/_images/admin11t.png)

Nota che è presente una ulteriore colonna «Cancellare?» che permette di rimuovere le righe aggiunte con il pulsante «Aggiungi un’altra scelta» e le righe che sono già state salvate.

## Personalizzazione della lista per la modifica dell’interfaccia di amministrazione

Ora che la pagina di amministrazione del modello Question sembra buona, facciamo qualche modifica alla pagina di «change list» – quella che mostra tutte le domande nel sistema.

Ecco come appare a questo punto:

![Pagina della lista dei cambiamenti dei sondaggi](intro/_images/admin04t.png)

By default, Django displays the `str()` of each object. But sometimes it’d be
more helpful if we could display individual fields. To do that, use the
[`list_display`](/it/6.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display) admin option, which is a
list of field names to display, as columns, on the change list page for the
object:

*`polls/admin.py`*

```python
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ["question_text", "pub_date"]
```

Di buona norma, aggiungiamo il metodo `was_published_recently()` da [Tutorial 2](/it/6.0/intro/tutorial02/):

*`polls/admin.py`*

```python
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ["question_text", "pub_date", "was_published_recently"]
```

Ora la pagina di elenco delle domande ha questo aspetto:

![La pagina dei cambiamenti relativi ai sondaggi, aggiornata](intro/_images/admin12t.png)

Puoi fare click sull’intestazione delle colonne per ordinare quei valori – eccetto nel caso di `was_published_recently` perchè l’ordinamento dell’output di un metodo non è supportato. Nota anche che l’intestazione di colonna per `was_published_recently` è, di default, il nome del metodo (con gli underscore a rimpiazzare gli spazi), e che ogni linea contiene la rappresentazione in stringa dell’oggetto.

You can improve that by using the [`display()`](/it/6.0/ref/contrib/admin/#django.contrib.admin.display)
decorator on that method (extending the `polls/models.py` file that was
created in [Tutorial 2](/it/6.0/intro/tutorial02/)), as follows:

*`polls/models.py`*

```python
from django.contrib import admin

class Question(models.Model):
    # ...
    @admin.display(
        boolean=True,
        ordering="pub_date",
        description="Published recently?",
    )
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now
```

Per più informazioni sulle proprietà configurabili attraverso il decoratore, vedi [`list_display`](/it/6.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display).

Modifica nuovamente il tuo file `polls/admin.py` e aggiungi un miglioramento alla pagina dell’elenco di modifiche `Domanda`: i filtri usando [`list_filter`](/it/6.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter). Aggiungi la seguente riga in `QuestionAdmin`:

```
list_filter = ["pub_date"]
```

Questo aggiunge una sidebar «Filtra» che permette all’utente di filtrare la lista per il campo `pub_date`:

![La pagina dei cambiamenti relativi ai sondaggi, aggiornata](intro/_images/admin13t.png)

Il tipo di filtro visualizzato dipende dal tipo di campo su cui stai filtrando. Poiché `pub_date` è un [`DateTimeField`](/it/6.0/ref/models/fields/#django.db.models.DateTimeField), Django sa fornire le opzioni di filtro appropriate: «Qualsiasi data», «Oggi», «Ultimi 7 giorni», «Questo mese», «Quest’anno».

Sta venendo su bene. Aggiungiamo alcune funzionalità di ricerca:

```
search_fields = ["question_text"]
```

Ciò aggiunge una casella di ricerca all’inizio dell’elenco delle modifiche. Quando qualcuno inserisce i termini di ricerca, Django cercherà nel campo `question_text`. Puoi utilizzare tutti i campi che desideri – anche se poiché utilizza una query `LIKE` dietro le quinte, limitare il numero di campi di ricerca a un numero ragionevole renderà più facile per il tuo database fare la ricerca.

Adesso è anche un buon momento per notare che le liste dei cambiamenti ti danno la paginazione gratis. Di default, mostra 100 elementi per pagina. [`Change list pagination`](/it/6.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_per_page), [`search boxes`](/it/6.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields), [`filters`](/it/6.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter), [`date-hierarchies`](/it/6.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.date_hierarchy), e [`column-header-ordering`](/it/6.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display) lavorano tutti assieme come pensi che dovrebbero.

## Personalizza l’aspetto dell’amministrazione

Chiaramente, avere «Django administration» nella parte superiore di ogni pagina di amministrazione è ridicolo. È solo testo segnaposto.

Puoi comunque cambiarlo, usando il sistema di template di Django. L’admin di Django è costruita su Django stesso, e dunque le sue interfacce usano il sistema di template di Django.

### Personalizzare i template del tuo *progetto*

Create a `templates` directory in your `djangotutorial` directory.
Templates can live anywhere on your filesystem that Django can access. (Django
runs as whatever user your server runs.) However, keeping your templates within
the project is a good convention to follow.

Apri il tuo file delle impostazioni (`mysite/settings.py`, ricorda) e aggiungi un’opzione [`DIRS`](/it/6.0/ref/settings/#std-setting-TEMPLATES-DIRS) nell’impostazione [`TEMPLATES`](/it/6.0/ref/settings/#std-setting-TEMPLATES):

*`mysite/settings.py`*

```python
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]
```

[`DIRS`](/it/6.0/ref/settings/#std-setting-TEMPLATES-DIRS) è una lista di directory su disco da controllare quando si caricano i template di Django; è un percorso di ricerca.

> **Organizzazione dei template**
>
> Proprio come i file statici, *potremmo* avere tutti i nostri modelli insieme, in una grande directory di modelli, e funzionerebbe perfettamente. Tuttavia, i modelli che appartengono a una particolare applicazione dovrebbero essere collocati nella directory dei modelli dell’applicazione(es. `polls/templates`) piuttosto che in quelli del progetto (`templates`). Discuteremo più in dettaglio nel [reusable apps tutorial](/it/6.0/intro/reusable-apps/)  *perché* lo facciamo.

Now create a directory called `admin` inside `templates`, and copy the
template `admin/base_site.html` from within the default Django admin
template directory in the source code of Django itself
([django/contrib/admin/templates](https://github.com/django/django/blob/stable/6.0.x/django/contrib/admin/templates)) into that directory.

> **Dove sono i file sorgenti di Django?**
>
> Se hai difficoltà a trovare dove si trovano i file sorgente di Django sul tuo sistema, esegui il seguente comando:
>
> ```console
> $ python -c "import django; print(django.__path__)"
> ```
>
> *Windows*
>
> ```doscon
> ...\> py -c "import django; print(django.__path__)"
> ```

Quindi, modifica il file e sostituisci `{{ site_header|default:_('Django administration') }}` (comprese le parentesi graffe) con il nome del tuo sito come meglio credi. Dovresti finire con una sezione di codice tipo:

```html+django
{% block branding %}
<div id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></div>
{% if user.is_anonymous %}
  {% include "admin/color_theme_toggle.html" %}
{% endif %}
{% endblock %}
```

Usiamo questo approccio per insegnarti come sovrascrivere i modelli. In un progetto reale, probabilmente useresti l’attributo: [`django.contrib.admin.AdminSite.site_header`](/it/6.0/ref/contrib/admin/#django.contrib.admin.AdminSite.site_header) per realizzare più facilmente questa particolare personalizzazione.

Questo file di template contiene molto testo come `{% block branding %}` e `{{ title }}`. I tag `{%` e `{{` sono parte del linguaggio di template di Django. Quando Django mostra `admin/base_site.html`, questo linguaggio di template sarà valutato per produrre la pagina HTML finale, come abbiamo visto in [Tutorial 3](/it/6.0/intro/tutorial03/).

Nota che qualsiasi template predefinito del pannello di amministrazione di Django può essere sovrascritto. Per sovrascrivere un template, fai la stessa cosa che hai fatto con `base_site.html` – copialo dalla directory predefinita nella tua directory personalizzata e apporta le modifiche.

### Personalizzare i template della tua *applicazione*

I lettori più attenti chiederanno: Ma se: l’impostazione: DIRS \<TEMPLATES-DIRS\> era vuota per impostazione predefinita, come ha fatto Django a trovare i modelli di amministrazione predefiniti? La risposta è che, poiché [`APP_DIRS`](/it/6.0/ref/settings/#std-setting-TEMPLATES-APP_DIRS)  è impostato su `True`, Django cerca automaticamente una sottodirectory `templates/` all’interno di ogni pacchetto dell’applicazione, da usare come fallback (non dimenticare che `django.contrib.admin` è un’applicazione).

La nostra applicazione per i sondaggi non è molto complessa e non necessita di modelli di admin personalizzati. Ma se diventasse più sofisticato e richiedesse la modifica dei modelli di amministrazione standard di Django per alcune delle sue funzionalità, sarebbe più sensato modificare i modelli *nell’applicazione*, piuttosto che quelli nel *progetto*. In questo modo, potresti includere l’applicazione sondaggi in qualsiasi nuovo progetto e avere la certezza che troverà i modelli personalizzati di cui ha bisogno.

Vedi la [documentazione sul caricamento dei template](/it/6.0/topics/templates/#template-loading) per ulteriori informazioni su come Django trova i suoi template.

## Personalizza l’indice dell’amministrazione

In modo simile, potresti voler personalizzare l’aspetto della pagina dell’indice di amministrazione di Django.

Di default, mostra tutte le app in [`INSTALLED_APPS`](/it/6.0/ref/settings/#std-setting-INSTALLED_APPS) che sono state registrate con l’applicazione di admin, in ordine alfabetico. Potresti voler apportare modifiche significative al layout. Dopotutto, l’indice è probabilmente la pagina più importante dell’amministratore e dovrebbe essere facile da usare.

The template to customize is `admin/index.html`. (Do the same as with
`admin/base_site.html` in the previous section – copy it from the default
directory to your custom template directory). Edit the file, and you’ll see it
uses a template variable called `app_list`. That variable contains every
installed Django app. Instead of using that, you can hardcode links to
object-specific admin pages in whatever way you think is best.

When you’re comfortable with the admin, read [part 8 of this
tutorial](/it/6.0/intro/tutorial08/) to learn how to use third-party packages.
