# Documentazione Django 6.0.7

# Come creare model field personalizzati

## Introduzione

La documentazione model reference spiega come usare i campi delle classi standard di Django – `CharField`, `DateField`, ecc. La maggior parte delle volte, queste classi sono tutto ciò di cui hai bisogno. A volte, però, la versione di Django non incontrerà precisamente i tuoi requisiti o vorrai usare un campo che è totalmente differente da quelli che sono forniti con Django.

I tipi di campi built-in di Django non coprono ogni possibile tipologia di colonna di database – sono i tipi più comuni, come `VARCHAR` e `INTEGER`. Per tipi di colonne più oscuri, come poligoni geografici o anche tipi creati dall’utente come i PostgreSQL custom types, puoi definire le tue sottoclassi di Django `Field`.

Alternativamente, puoi avere un oggetto Python complesso che può essere serializzato in qualche modo per essere accolto in un tipo di colonna standard di database. Questo è un ulteriore caso in cui una sottoclasse di `Field` ti aiuterà ad usare il tuo oggetto con i tuoi modelli.

### Il nostro oggetto di esempio

Creating custom fields requires a bit of attention to detail. To make things easier to follow, we’ll use a consistent example throughout this document: wrapping a Python object representing the deal of cards in a hand of Bridge. Don’t worry, you don’t have to know how to play Bridge to follow this example. You only need to know that 52 cards are dealt out equally to four players, who are traditionally called north, east, south and west. Our class looks something like this:

    class Hand:
        """A hand of cards (bridge style)"""

        def __init__(self, north, east, south, west):
            # Input parameters are lists of cards ('Ah', '9s', etc.)
            self.north = north
            self.east = east
            self.south = south
            self.west = west

        # ... (other possibly useful methods omitted) ...

Questa è una classe Python ordinaria, senza niente che sia specifico di Django. Ci piacerebbe fare cose come questa nel nostro modello (assumiamo che l’attributo «hand» sul modello sia istanza di `Hand`):

    example = MyModel.objects.get(pk=1)
    print(example.hand.north)

    new_hand = Hand(north, east, south, west)
    example.hand = new_hand
    example.save()

Assegniamo e ritiriamo l’attributo `hand` nel nostro modello proprio come qualsiasi altra classe Python. Il trucco è dire a Django come gestire il salvataggio ed il caricamento su e da questo oggetto.

Per usare la classe `Hand` nei nostri models, non dobbiamo cambiare assolutamente la classe. Questo è l’ideale, perchè significa che puoi scrivere facilmente modelli che supportano classi esistenti dove non puoi cambiare il codice sorgente.

Nota

Potresti anche solo voler trarre vantaggio dai tipi custom per le colonne di database ed avere a che fare con i dati come tipi standard di Python nei modelli; stringhe o float, per esempio. Questo caso è simile al nostro esempio `Hand` e terremo nota delle differenze andando avanti.

## Teoria di Background

### Stoccaggio DB

Cominciamo con i campi di model. Se lo riduci ai minimi termini, un campo model offre un modo di prendere un normale oggetto Python – stringa, booleano, `datetime` or qualcosa di più complesso come `Hand` – e convertirlo a e da un formato che è utile quando si ha a che fare con il database. (Questo formato è anche utile per la serializzazione ma, come vedremo più tardi, è una cosa facile una volta che hai sotto controllo il database).

I campi di un modello devono in qualche modo essere convertiti per stare in un tipo esistente di colonna di database. Diversi database offrono diversi set di tipi di colonna validi ma la regola è sempre la stessa: sono gli unici tipi con cui puoi lavorare. Qualsiasi cosa tu voglia scrivere sul database, deve poter essere rappresentato con quei tipi.

Normalmente, stai scrivendo un campo Django che sia consono per uno dei tipi di colonna del database oppure ti servirà un modo di convertire i tuoi dati, per dire, in una stringa.

Per il nostro esempio `Hand`, potremmo convertire i dati della carta in una stringa di 104 caratteri concatenando tutte le carte insieme in un ordine predeterminato – diciamo, prima tutte le carte nord, poi est, * carte sud* e ovest. In questo modo gli oggetti `Hand` possono essere salvati in colonne testuali o di caratteri nel database.

### Cosa fa una classe di campo?

Tutti i campi Django (e quando parliamo di campi in questo documento, intendiamo sempre campi del modello e non form fields) sono sottoclassi di `django.db.models.Field`. La maggior parte delle informazioni che Django registra su un campo sono comuni per tutti i campi – nome, testo di aiuto, unicità e così via. La registrazione di tutte quelle informazioni è gestita da `Field`. Ci addentreremo nei dettagli di ciò che `Field` può fare più tardi; per ora, è sufficiente dire che ogni cosa discende da `Field` e poi personalizza pezzi chiave del comportamento della classe.

E” importante capire che una classe per un campo di Django non è quel che è salvato negli attributi del model. Gli attributi del model contengono oggetti Python normali. Le classi per i campi che definisci in un model sono salvati nella classe `Meta` quando la classe del model viene creata (i dettagli precisi di come questo avvenga ora non sono importanti). Questo accade perchè le classi dei campi non sono necessarie quando stai creando o modificando attributi. Invece, offrono i meccanismi per convertire il valore dell’attributo in quel che viene salvato sul database o mandato al serializzatore.

Tieni a mente questo quando crei i tuoi campi personalizzati. La sottoclasse `Field` di Django che scrivi offre i meccanismi per la conversione tra le tue istanze di Python ed i valori del database/serializzatore in diversi modi (ci sono differenze tra salvare un valore ed usarlo per un lookup, per esempio). Se ti sembra un po” complicato, non preoccuparti – diverrà più chiaro negli esempi che seguono. Ricordati solo che finirai spesso a creare due classi quando vuoi un campo personalizzato:

- La prima classe è l’oggetto Python che i tuoi utenti manipoleranno. Lo assegneranno all’attributo model, leggeranno da esso per la visualizzazione, cose del genere. Questa è la classe `Hand` nel nostro esempio.

- La seconda classe è la sottoclasse `Field`. Questa è la classe che sa come riconvertire la tua prima classe avanti ed indietro tra la sua forma di salvataggio permanente e la sua forma in Python.

## Scrivere una sottoclasse di campo

Quando pianifichi la tua sottoclasse `Field`, prova a pensare a quale classe `Field` esistente somigli. Puoi fare una sottoclasse di un campo Django esistente e risparmiarti un po” di lavoro? Se non puoi, dovresti fare una sottoclasse di `Field`, dalla quale tutto discende.

Inizializzare il tuo nuovo campo è questione di fare una separazione tra gli argomenti che sono specifici per il tuo caso da quelli comuni e passare questi ultimi nel metodo `__init__()` di `Field` (o della tua classe padre).

Nel nostro esempio, chiameremo il nostro campo `HandField`. (E” una buona idea chiamare la tua sottoclasse di `Field` `<Something>Field`, così che sia facilmente identificabile come `Field` subclass.). Non deve comportarsi come alcun campo esistente, così faremo direttamente una sottoclasse di `Field`:

    from django.db import models

    class HandField(models.Field):
        description = "A hand of cards (bridge style)"

        def __init__(self, *args, **kwargs):
            kwargs["max_length"] = 104
            super().__init__(*args, **kwargs)

Il nostro `HandField` accetta la maggior parte delle opzioni standard per un campo (vedi la lista qui sotto) ma ci assicuriamo che abbia una lunghezza fissa, perchè necessita di tenere solo i valori delle 52 carte più i loro semi; 104 caratteri in tutto.

Nota

Molti dei modelli di Django accettano opzioni con le quali poi non fanno niente. Per esempio, puoi passare sia `editable` che `auto_now` ad una `django.db.models.DateField` ed ignorerà il parametro `editable` (impostare `auto_now` implica `editable=False`). Non viene sollevato alcun errore in questo caso.

Questo comportamento semplifica le classi per i campi perchè non hanno bisogno di controllare le opzioni che non sono necessarie. Passano tutte le opzioni al padre e poi non le usano. Sta a te essere più o meno esigente riguardo alle opzioni che selezionano o utilizzare il comportamento più permissivo per i campi correnti.

Il metodo `Field.__init__()` accetta i seguenti parametri:

- `verbose_name`

- `name`

- `primary_key`

- `max_length`

- `unique`

- `blank`

- `null`

- `db_index`

- `rel`: Usato per campi collegati (come `ForeignKey`). Solo per utenti avanzati.

- `default`

- `editable`

- `serialize`: Se `False`, il campo non verrà serializzato quando viene passato ai serializers di Django. Di default a `True`.

- `unique_for_date`

- `unique_for_month`

- `unique_for_year`

- `choices`

- `help_text`

- `db_column`

- `db_tablespace`: solo per la creazione dell’indice, se il backend supporta tablespaces. Generalmente puoi ignorare questa opzione.

- `auto_created`: `True` se il campo è stato creato automaticamente, come per `OneToOneField`, usato per l’ereditarietà del model. Solo per uso avanzato.

Tutte le opzioni che non hanno una spiegazione nella lista precedente hanno lo stesso significato che avrebbero nei normali campi Django. Vedi la documentazione dei campi per esempi e dettagli.

### Scomposizione di un campo

Il duale rispetto allo scrivere il metodo `__init__()` è scrivere il metodo `deconstruct()`. Viene utilizzato durante model migrations per dire a Django come prendere un’istanza del tuo nuovo campo e ridurlo ad una forma serializzata, in particolare, quali argomenti passare a `__init__()` per ricrearlo.

Se non hai aggiunto opzioni extra sul campo dal quale hai ereditato, allora non c’è bisogno di scrivere un nuovo metodo `deconstruct()`. Se, comunque, stai cambiando gli argomenti da passare ad `__init__()` (come stiamo facendo in `HandField`), avrai bisogno di integrare i valori da passare.

`deconstruct()` restituisce una tupla di 4 elementi: il nome dell’attributo del campo, l’import path completo della classe del campo, i positional arguments (come lista) ed i keyword arguments (come dizionario). Nota che questo è differente dal metodo `deconstruct()` per la classi custom che restituisce una tupla di tre cose.

Come autore di un campo custom, non devi preoccuparti dei primi due valori; la classe di base `Field` ha tutto il codice per gestire l’attributo relativo al nome del campo ed al percorso di importazione. Devi, in ogni caso, fare attenzione ai positional e keyword arguments, perchè molto probabilmente sono quelli che stai cambiando.

Per esempio, nella nostra classe `HandField` stiamo già forzosamente impostando max_length in `__init__()`. Il metodo `deconstruct()` sulla classe base `Field` ne terrà conto e cercherà di restituirlo tra i keyword arguments; quindi, possiamo eliminarlo dai keyword arguments per questioni di leggibilità:

    from django.db import models

    class HandField(models.Field):
        def __init__(self, *args, **kwargs):
            kwargs["max_length"] = 104
            super().__init__(*args, **kwargs)

        def deconstruct(self):
            name, path, args, kwargs = super().deconstruct()
            del kwargs["max_length"]
            return name, path, args, kwargs

Se aggiungi un nuovo keyword argument, dovrai scrivere da te del codice in `deconstruct()` che metta il suo valore in `kwargs`. Dovresti anche omettere il valore da `kwargs` quando non sia necessario ricostruire lo stato del campo, per esempio quando se ne usa il valore predefinito:

    from django.db import models

    class CommaSepField(models.Field):
        "Implements comma-separated storage of lists"

        def __init__(self, separator=",", *args, **kwargs):
            self.separator = separator
            super().__init__(*args, **kwargs)

        def deconstruct(self):
            name, path, args, kwargs = super().deconstruct()
            # Only include kwarg if it's not the default
            if self.separator != ",":
                kwargs["separator"] = self.separator
            return name, path, args, kwargs

Esempi più complessi sono oltre le finalità di questo documento ma ricorda - per ogni configurazione della tua istanza di Field, `deconstruct()` deve restituire argomenti che si possano passare ad `__init__` per ricostruire lo stato.

Fai particolarmente attenzione se imposti nuovi valori di default nella superclasse di `Field`; vuoi essere sicuro che siano sempre inclusi piuttosto che sparire se dovessero riprendere il vecchio valore di default.

Inoltre, cerca di evitare di restituire valori come positional arguments; dove possibile, restituisci valori come argomenti keyword per massimizzare la compatibilità futura. Se cambi il nome delle cose più spesso della loro posizione nella lista di argomenti del costruttore, potresti preferire i positional ma tieni in mente che molte persone ricostruiranno il campo a partire dalla versione serializzata per un po” (anche anni), dipendentemente da quanto a lungo vivranno le tue migrazioni.

Puoi osservare i risultati della decostruzione guardando nelle migrazioni che includono il campo, e puoi testare la decostruzione negli unit test, decostruendo e ricostruendo il campo:

    name, path, args, kwargs = my_field_instance.deconstruct()
    new_instance = MyField(*args, **kwargs)
    self.assertEqual(my_field_instance.some_attribute, new_instance.some_attribute)

### Attributi di campo che non interessano la definizione di colonne di database

Puoi sovrascrivere `Field.non_db_attrs` per personalizzare gli attributi di un campo che non influiscono sulla definizione di una colonna. Viene utilizzato durante le migrazioni dei modelli per rilevare `AlterField` no-op.

Per esempio:

    class CommaSepField(models.Field):
        @property
        def non_db_attrs(self):
            return super().non_db_attrs + ("separator",)

### Cambiare la classe base di un campo personalizzato

Non puoi cambiare la classe base di un campo custom perchè Django non si accorgerà del cambiamento e non potrà creare una migrazione di conseguenza. Per esempio, se cominci con:

    class CustomCharField(models.CharField): ...

e poi decidi che vuoi usare un `TextField`, non puoi cambiare la sottoclasse così:

    class CustomCharField(models.TextField): ...

Invece, devi creare una nuova classe per il campo personalizzato ed aggiornare il modello per farvi riferimento:

    class CustomCharField(models.CharField): ...

    class CustomTextField(models.TextField): ...

Come discusso in rimuovere campi, devi mantenere la classe originale `CustomCharField` fintanto che hai migrazione che vi facciano riferimento.

### Documentare il tuo campo personalizzato

Come sempre, dovresti documentare il tuo tipo di campo, così che gli utenti possano sapere cosa sia. Oltre a fornire una docstring, che è utile per gli sviluppatori, dovresti anche mettere in condizioni gli utenti dell’amministrazione di vedere una piccola descrizione del tipo di campo tramite l’applicazione django.contrib.admindocs . Per far questo, fornisci un testo descrittivo nell’attributo di classe `description` del tuo campo personalizzato. Nell’esempio sopracitato, la descrizione mostrata dall’applicazione `admindocs` per un `HandField` sarà “Una mano di carte (stile bridge)”.

Nella visualizzazione in `django.contrib.admindocs`, la descrizione del campo è interpolata con `field.__dict__`, che consente che la descrizione incorpori gli argomenti del campo. Per esempio, la descrizione di `CharField` è:

    description = _("String (up to %(max_length)s)")

### Metodi utili

Una volta che hai creato la tua sottoclasse di `Field`, puoi considerare di fare override di alcuni metodi standard, dipendentemente dal comportamento del tuo campo. La lista di metodi che segue è ordinata approssimativamente in ordine decrescente di importanza, quindi inizia dall’alto.

#### Tipi di database personalizzati

Supponiamo che tu abbia creato un tipo PostgreSQL custom chiamato mytype`. Puoi fare una sottoclasse di `Field` ed implementare il metodo `db_type()`, nel modo seguente:

    from django.db import models

    class MytypeField(models.Field):
        def db_type(self, connection):
            return "mytype"

Una volta che hai `MytypeField`, puoi usarlo in ogni modello, come qualsiasi altro tipo `Field`:

    class Person(models.Model):
        name = models.CharField(max_length=80)
        something_else = MytypeField()

Se punti ad implementare una applicazione agnostica rispetto al database, dovresti tenere in considerazione le differenze nei tipi di colonna del database. Per esempio, il tipo date/time in PostgreSQL è chiamato `timestamp`, mentre la stessa colonna in MySQL viene chiamata `datetime`. Puoi gestire tutto questo in un metodo `db_type()` controllando l’attributo `connection.vendor`. I nomi di vendor correntemente disponibili sono: `sqlite`, `postgresql`, `mysql` e``oracle``.

Per esempio:

    class MyDateField(models.Field):
        def db_type(self, connection):
            if connection.vendor == "mysql":
                return "datetime"
            else:
                return "timestamp"

The `db_type()` and `rel_db_type()` methods are called by Django when the framework constructs the `CREATE TABLE` statements for your application – that is, when you first create your tables. The methods are also called when constructing a `WHERE` clause that includes the model field – that is, when you retrieve data using QuerySet methods like `get()`, `filter()`, and `exclude()` and have the model field as an argument.

Some database column types accept parameters, such as `CHAR(25)`, where the parameter `25` represents the maximum column length. In cases like these, it’s more flexible if the parameter is specified in the model rather than being hardcoded in the `db_type()` method. For example, it wouldn’t make much sense to have a `CharMaxlength25Field`, shown here:

    # This is a silly example of hardcoded parameters.
    class CharMaxlength25Field(models.Field):
        def db_type(self, connection):
            return "char(25)"

    # In the model:
    class MyModel(models.Model):
        # ...
        my_field = CharMaxlength25Field()

Il miglior modo di fare una cosa del genere potrebbe essere rendere il parametro specificabile a run time – per esempio, quando la classe viene istanziata. Per fare ciò, implementa così `Field.__init__()`:

    # This is a much more flexible example.
    class BetterCharField(models.Field):
        def __init__(self, max_length, *args, **kwargs):
            self.max_length = max_length
            super().__init__(*args, **kwargs)

        def db_type(self, connection):
            return "char(%s)" % self.max_length

    # In the model:
    class MyModel(models.Model):
        # ...
        my_field = BetterCharField(25)

Infine, se la tua colonna richiede davvero un setup SQL complesso, restituisci `None` da `db_type()`. Questo farà in modo che Django salti questo campo durante la creazione del codice SQL. A questo punto sei in qualche modo il responsabile della creazione della colonna nella giusta tabella ma questo ti offre un modo di dire a Django di non agire.

Il metodo `rel_db_type()` è chiamato da campi come `ForeignKey` e `OneToOneField` che puntano ad altri campi per determinare il proprio tipo di dato per la colonna del database. Per esempio, se hai un `UnsignedAutoField`, hai anche bisogno delle foreign keys che puntano a quel campo e che usano lo stesso tipo di dato:

    # MySQL unsigned integer (range 0 to 4294967295).
    class UnsignedAutoField(models.AutoField):
        def db_type(self, connection):
            return "integer UNSIGNED AUTO_INCREMENT"

        def rel_db_type(self, connection):
            return "integer UNSIGNED"

#### Conversione di valori a oggetti Python

Se la tua classe personalizzata `Field` ha a che fare con strutture di dati che sono più complesse di stringhe, date, interi o numeri in virgola mobile, allora potresti aver bisogno di fare override di `from_db_value()` e `to_python()`.

Se presente per la sottoclasse del campo, `from_db_value()` sarà chiamato in tutte le circostanze in cui i dati sono caricati dal database, incluse le aggregazioni e le chiamate `values()`.

`to_python()` è chiamato per la deserializzazione e nel metodo `clean()` usato dai form.

Come regola generale, `to_python()` dovrebbe avere a che fare in modo graceful con i seguenti argomenti:

- Una istanza del tipo corretto (per esempio `Hand` nel nostro esempio).

- Una stringa

- `None` (se il campo permette `null=True`)

Nella nostra classe `HandField`, stiamo immagazinando i dati come un campo `VARCHAR` nel database, quindi dobbiamo essere in grado di processare string e `None` in from_db_value()`. In `to_python()`, dovremo anche gestire le istanze di `Hand`:

    import re

    from django.core.exceptions import ValidationError
    from django.db import models
    from django.utils.translation import gettext_lazy as _

    def parse_hand(hand_string):
        """Takes a string of cards and splits into a full hand."""
        p1 = re.compile(".{26}")
        p2 = re.compile("..")
        args = [p2.findall(x) for x in p1.findall(hand_string)]
        if len(args) != 4:
            raise ValidationError(_("Invalid input for a Hand instance"))
        return Hand(*args)

    class HandField(models.Field):
        # ...

        def from_db_value(self, value, expression, connection):
            if value is None:
                return value
            return parse_hand(value)

        def to_python(self, value):
            if isinstance(value, Hand):
                return value

            if value is None:
                return value

            return parse_hand(value)

Nota che restituiamo sempre una istanza di `Hand` da questi metodi. Quello è il tipo di oggetto Python che vogliamo salvare nell’attributo del model.

Per `to_python()`, se qualcosa va storto durante una conversione di valore, dovresti lanciare una eccezione `ValidationError`.

#### Convertire oggetti Python in query di valori

Poichè l’utilizzo di un database richiede conversioni in entrambi i sensi, se fai override di `from_db_value()` devi anche fare override di `get_prep_value()` per riconvertire gli oggetti Python in query values.

Per esempio:

    class HandField(models.Field):
        # ...

        def get_prep_value(self, value):
            return "".join(
                ["".join(l) for l in (value.north, value.east, value.south, value.west)]
            )

Avvertimento

Se il tuo campo custom usa tipi `CHAR`, `VARCHAR` o `TEXT` per MySQL, devi assicurarti che `get_prep_value()` restituisca sempre un tipo stringa. MySQL esegue match flessibili ed inaspettati quando si esegue una query su questi tipi ed il valore che si fornisce è un integer, che può causare l’inclusione di valori inattesi nei risultati. Questo problema non si pone se restituisci sempre un tipo stringa da `get_prep_value()`.

#### Convertire query values in valori di database

Alcuni tipi di dato (per esempio, date) devono trovarsi in uno specifico formato prima di poter essere usati da un backend database. `get_db_prep_value()` è il metodo in cui si dovrebbero effettuare queste conversioni. La connessione specifica che sarà usata per la query è passata come parametro `connection`. Questo ti permette usare logica specifica del backend per la coversione, se questa è richiesta.

Per esempio, Django usa il metodo seguente per il suo `BinaryField`:

    def get_db_prep_value(self, value, connection, prepared=False):
        value = super().get_db_prep_value(value, connection, prepared)
        if value is not None:
            return connection.Database.Binary(value)
        return value

Nel caso che il tuo campo personalizzato richieda una conversione speciale al salvataggio che non sia la stessa usata per i parametri di query, puoi fare override di `get_db_prep_save()`.

#### Pre elaborazione dei valori prima del salvataggio

Se vuoi preprocessare il valore proprio prima di salvarlo, puoi sare `pre_save()`. Per esempio, `DateTimeField` di Django usa questo metodo per impostare l’attributo correttamente in caso di `auto_now` o `auto_now_add`.

Se fai override di questo metodo, alla fine devi restituire il valore dell’attributo. Dovresti anche aggiornare l’attributo del model se fai cambiamenti al valore, così che il codice che abbia riferimenti al model possa sempre vedere il valore corretto.

#### Specificare il form field per un model field

Per personalizzare il campo del form usato da `ModelForm`, puoi fare override di `formfield()`.

La classe del campo del form può essere specificata con gli argomenti `form_class` e `choices_form_class`; il secondo è usato se il campo specifica delle scelte, altrimenti il primo. Se questi argomenti non sono forniti, saranno usati `CharField` or `TypedChoiceField`.

Tutto il dizionario `kwargs` viene passato direttamente nel metodo `__init__()` del form. Normalmente, tutto quel che devi fare è impostare un buon default per l’argomento `form_class` (e magari `choices_form_class`). Questo ti potrebbe richiedere di scrivere un campo form personalizzato (ed anche un form widget). Vedi documentazione dei form per avere informazioni su questo.

If you wish to exclude the field from the `ModelForm`, you can override the `formfield()` method to return `None`.

Continuando con il nostro esempio, possiamo scrivere il metodo `formfield()` come:

    class HandField(models.Field):
        # ...

        def formfield(self, **kwargs):
            # Exclude the field from the ModelForm when some condition is met.
            some_condition = kwargs.get("some_condition", False)
            if some_condition:
                return None

            # Set up some defaults while letting the caller override them.
            defaults = {"form_class": MyFormField}
            defaults.update(kwargs)
            return super().formfield(**defaults)

Questo presume che abbiamo importato una classe per il campo `MyFormField` (che ha il proprio widget predefinito). Questo documento non copre i dettagli relativi alla scrittura di form field personalizzati.

#### Emulare tipi di campo built-in

Se hai creato un metodo `db_type()`, non devi preoccuparti del `get_internal_type()` – non verrà usato spesso. Qualche volta, però, lo storage del tuo database è di tipo simile a quello di qualche altro campo, quindi puoi usare la logica di quest’altro campo per creare la giusta colonna.

Per esempio:

    class HandField(models.Field):
        # ...

        def get_internal_type(self):
            return "CharField"

Non importa quale database stiamo usando per il backend, questo significa che `migrate` e altri comandi SQL creano il giusto tipo di colonna per il salvataggio di una stringa.

Se `get_internal_type()` ritorna una stringa che non è nota a Django per il database di backend che stai utilizzando – cioè, non appare in `django.db.backends.<db_name>.base.DatabaseWrapper.data_types` – la stringa sarà ugualmente usata dal serializzatore, ma il metodo di default `db_type()` ritornerà `None`. Vedi la documentazione di `db_type()` per capire i motivi per cui questo potrebbe essere utile. Inserire una stringa descrittiva come tipo del campo per il serializzatore è una buona idea semmai dovessi usare l’output del serializzatore da qualche altra parte, al di fuori di Django.

#### Conversione dei dati del campo per la serializzazione

Per personalizzare il modo in cui i valori vengono serializzati da un serializzatore, puoi fare l’override di `value_to_string()`. Usare `value_from_object()` è il modo migliore di ottenere il valore del campo prima della serializzazione. Ad esempio, dato che `HandField` usa delle stringhe per il salvataggio dei dati, possiamo riutilizzare una parte del codice di conversione esistente.

    class HandField(models.Field):
        # ...

        def value_to_string(self, obj):
            value = self.value_from_object(obj)
            return self.get_prep_value(value)

### Alcuni consigli generali

Scrivere un campo personalizzato può essere un processo complesso, in particolar modo se stai facendo delle conversioni complesse tra i tipi di dati Python e il tuo database e i formati di serializzazione. Ecco alcuni suggerimenti per rendere le cose più semplici:

1. Look at the existing Django fields (in django/db/models/fields/__init__.py) for inspiration. Try to find a field that’s similar to what you want and extend it a little bit, instead of creating an entirely new field from scratch.

2. Metti un metodo `__str__()` sulla classe che stai incapsulando come campo. Ci sono molti casi in cui il comportamento di default del campo è quello di chaimare `str()` sul valore. (Negli esempi in questo documento, value` potrebbe essere una istanza di `Hand`, non un `HandField`). Così, se il tuo metodo `__str__()` converte automaticamente in stringa il tuo oggetto Python, puoi risparmiarti un sacco di lavoro.

## Scrivere una sottoclasse `FileField`

Oltre ai metodi sopra, i campi che hanno a che fare con i file hanno pochi altri requisiti speciali che è necessario prendere in considerazione. La maggior parte delle meccaniche fornite da `FileField`, come il controllo dello storage e del ritiro su e dal database, possono rimanere inalterate, lasciando alle sottoclassi l’onere di supportare un determinato tipo di file.

Django fornisce una classe `File`, che viene utilizzata come proxy per accedere ai contenuti del file e compiere operazioni. A partire da questa si possono creare delle sottoclassi per personalizzare le modalità di accesso al file ed i metodi disponibili. Si tratta di `django.db.models.fields.files` ed il suo comportamento standard viene spiegato nella documentazione dei file.

Una volta creata una sottoclasse di File`, è necessario dire alla nuova sottoclasse di `FileField` di usarla. Per farlo, assegna la nuova sottoclasse `File` all’attributo speciale `attr_class` della sottoclasse `FileField`.

### Alcuni suggerimenti

In aggiunta ai dettagli precedentemente esposti, ci sono alcune linee guida che possono migliorare notevolmente l’efficienza e la leggibilità del codice del campo.

1. The source for Django’s own `ImageField` (in django/db/models/fields/files.py) is a great example of how to subclass `FileField` to support a particular type of file, as it incorporates all of the techniques described above.

2. Metti in cache i file quando possibile. Dal momento che i file potrebbero trovarsi su sistemi di storage remoti, ritirarli potrebbe costare tempo o addirittura denaro aggiuntivo, cosa che non è sempre necessaria. Una volta che un file è stato ritirato per ottenere dati relativi al suo contenuto, metti in cache quanti più dati possibile per ridurre il numero di volte che il file deve essere ritirato per chiamate susseguenti relative a quelle informazioni.