00
:
00
:
00
:
00
•Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

User Model Personalizzato

Django raccomanda di definire un modello utente personalizzato all’inizio di ogni nuovo progetto, anche se il modello predefinito sembra sufficiente. Cambiare il modello utente dopo aver eseguito le migrazioni e estremamente complicato, quindi e meglio farlo subito.

Perche Personalizzare il Modello User

Il modello User predefinito di Django richiede username e password. In molti progetti moderni pero l’autenticazione avviene tramite email. Un modello personalizzato permette di:

  • Usare l’email come campo di login
  • Aggiungere campi personalizzati direttamente al modello utente
  • Avere il pieno controllo sul comportamento dell’autenticazione

Approccio 1: AbstractUser

AbstractUser estende il modello utente predefinito mantenendo tutti i campi e le funzionalita esistenti. E l’approccio piu semplice:

# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    email = models.EmailField(unique=True)
    telefono = models.CharField(max_length=20, blank=True)
    data_nascita = models.DateField(null=True, blank=True)
    avatar = models.ImageField(upload_to='avatars/', blank=True)
    bio = models.TextField(max_length=500, blank=True)

    def __str__(self):
        return self.email

Configura il modello nelle impostazioni:

# settings.py
AUTH_USER_MODEL = 'accounts.CustomUser'

Registra il modello nell’admin:

# accounts/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser

@admin.register(CustomUser)
class CustomUserAdmin(UserAdmin):
    model = CustomUser
    list_display = ['username', 'email', 'telefono', 'is_staff']

    fieldsets = UserAdmin.fieldsets + (
        ('Informazioni Aggiuntive', {
            'fields': ('telefono', 'data_nascita', 'avatar', 'bio'),
        }),
    )

    add_fieldsets = UserAdmin.add_fieldsets + (
        ('Informazioni Aggiuntive', {
            'fields': ('email', 'telefono'),
        }),
    )

Approccio 2: AbstractBaseUser

AbstractBaseUser offre il massimo controllo ma richiede di definire tutto da zero. Usalo quando hai bisogno di un modello utente completamente diverso:

# accounts/models.py
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.db import models
from django.utils import timezone

class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    nome = models.CharField(max_length=50)
    cognome = models.CharField(max_length=50)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    date_joined = models.DateTimeField(default=timezone.now)

    USERNAME_FIELD = 'email'        # campo usato per il login
    REQUIRED_FIELDS = ['nome', 'cognome']  # campi richiesti da createsuperuser

    objects = CustomUserManager()

    def __str__(self):
        return self.email

    def get_full_name(self):
        return f"{self.nome} {self.cognome}"

    def get_short_name(self):
        return self.nome

Custom User Manager

Con AbstractBaseUser devi definire un manager personalizzato:

# accounts/models.py
from django.contrib.auth.models import BaseUserManager

class CustomUserManager(BaseUserManager):
    def create_user(self, email, nome, cognome, password=None, **extra_fields):
        if not email:
            raise ValueError("L'indirizzo email e obbligatorio.")
        email = self.normalize_email(email)
        user = self.model(email=email, nome=nome, cognome=cognome, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, nome, cognome, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError("Il superuser deve avere is_staff=True.")
        if extra_fields.get('is_superuser') is not True:
            raise ValueError("Il superuser deve avere is_superuser=True.")

        return self.create_user(email, nome, cognome, password, **extra_fields)

Usare get_user_model()

In tutto il progetto, per riferirsi al modello utente usa sempre get_user_model() invece di importare direttamente il modello:

from django.contrib.auth import get_user_model
from django.db import models

User = get_user_model()

class Articolo(models.Model):
    autore = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='articoli'
    )
    titolo = models.CharField(max_length=200)

Nelle impostazioni e nei file di configurazione usa la stringa AUTH_USER_MODEL:

from django.conf import settings
from django.db import models

class Commento(models.Model):
    autore = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    testo = models.TextField()

La sintassi settings.AUTH_USER_MODEL e preferita nei modelli perche funziona correttamente con il sistema di migrazioni.

Considerazioni sulle Migrazioni

E fondamentale definire AUTH_USER_MODEL prima di eseguire la prima migrazione:

# 1. Crea l'app accounts
# python manage.py startapp accounts

# 2. Definisci il modello CustomUser in accounts/models.py

# 3. Aggiungi AUTH_USER_MODEL in settings.py
# AUTH_USER_MODEL = 'accounts.CustomUser'

# 4. Aggiungi 'accounts' a INSTALLED_APPS

# 5. Crea e applica le migrazioni
# python manage.py makemigrations accounts
# python manage.py migrate

Se il progetto ha gia delle migrazioni con il modello User predefinito, cambiare AUTH_USER_MODEL richiede di ricreare il database da zero.

Form di Registrazione per User Personalizzato

Adatta il form di registrazione al modello personalizzato:

# accounts/forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import get_user_model

User = get_user_model()

class CustomUserCreationForm(UserCreationForm):
    class Meta:
        model = User
        fields = ['email', 'nome', 'cognome', 'password1', 'password2']

Conclusione

Personalizzare il modello utente e una delle prime decisioni da prendere in un progetto Django. AbstractUser e la scelta migliore nella maggior parte dei casi, poiche mantiene tutte le funzionalita predefinite aggiungendo i campi necessari. AbstractBaseUser offre il controllo totale ma richiede piu codice. In entrambi i casi, ricorda sempre di usare get_user_model() e settings.AUTH_USER_MODEL nel resto del progetto.