Résolue

Erreur lors de la création des migrations

# Résolution d'erreurs # Django # Migrations

Bonjour Thibault,
J'ai suivi pas à pas la vidéo "Créer une vue d'inscription personnalisée". A la 2e minute de la vidéo, on crée les migrations.
Ce m'affiche le message d'erreur suivant :
"django.core.exceptions.FieldError: Unknown field(s) (username) specified for CustomUser"
J'ai beau tout retourner mais je n'arrive pas à savoir à quoi c'est dû.
Pourriez-vous m'éclairer ?
Merci d'avance.

Voici une copie du fichier models.py

from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager

from django.db import models

class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError("Vous devez entrer un email.")
user = self.model(email=self.normalize_email(email))
user.set_password(password)
user.save()
return user

def create_superuser(self, email,  password=None):
    user = self.create_user(email=email, password=password)
    user.is_admin = True
    user.is_staff = True
    user.save()
    return user

class CustomUser(AbstractBaseUser):
email = models.EmailField(
unique=True,
blank=False,
max_length=255
)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)

USERNAME_FIELD = "email"
objects = MyUserManager()

def has_perm(self, perm, obj=None):
    return True

def has_module_perms(self, app_label):
    return True

Thibault houdon

Mentor

Salut ! Pas de souci, on va débugger ça ensemble.

L'erreur dit que Django ne connaît pas le champ "username" pour le modèle "CustomUser". Dans ton modèle "CustomUser", tu as bien indiqué "email" comme "USERNAME_FIELD", donc c'est ce champ que Django devrait utiliser comme nom d'utilisateur.

Je pense que tu as peut-être oublié de changer le fichier "settings.py". Essaie d'ajouter la ligne suivante pour indiquer à Django que le modèle à utiliser pour les utilisateurs est bien "CustomUser" :

AUTH_USER_MODEL = 'nom_de_ton_application.CustomUser'

Il faut bien sûr remplacer "nom_de_ton_application" par le nom de l'app où tu as défini le modèle "CustomUser".

On fait cette étape quelques sessions avant danse cours (https://www.docstring.fr/formations/la-gestion-des-utilisateurs-avec-django/la-classe-abstractuser-1387/?tab=transcription#t=207.0) donc tu l'as peut être manqué :)

Bonjour Thibault,
Merci pour ta réponse.
Jai bien mis à jour le fichier de settings (cf ci-dessous) et c'est la première chose que j'ai regardée.

Default primary key field type

https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

LOGIN_REDIRECT_URL = "page_index" # Ajouté par RAM
LOGIN_URL = "page_index" # Ajouté par RAM

Permet d'accepter des chemins d'url sans slash final

APPEND_SLASH = True

AUTH_USER_MODEL = "accounts.CustomUser"

Thibault houdon

Mentor

Salut !

Ok oui ça semble correct. N'oublie pas, après avoir modifié ton modèle d'utilisateur, de faire une migration avec les commandes suivantes :

python manage.py makemigrations
python manage.py migrate

Si ça ne fonctionne toujours pas, une autre raison pour laquelle tu pourrais avoir cette erreur serait si tu essaies d'utiliser un formulaire Django par défaut qui utilise "username" comme champ de formulaire (comme UserCreationForm ou AuthenticationForm), parce que dans ton modèle d'utilisateur custom, tu n'as pas de champ "username". Essaye de vérifier cette partie aussi.

Derniere possibilité mais jimagine que depuis le temps tu l'as déja essayé, c'est le serveur Django qui a besoin d'un bon vieux redémarrage pour prendre en compte les derniers changements. Donc essaye de stopper le serveur et de le redémarrer pour voir si ça aide.

Re-bonjour Thubault,
C'est l'instruction python manage.py makemigrations qui génère le message d'erreur. Du coup je ne peux pas aller plus loin.
Quand je redémarre le serveur Django, c'est la fête :-) Voici le message d'erreur :

Performing system checks...

Watching for file changes with StatReloader
Exception in thread django-main-thread:
Traceback (most recent call last):
File "C:\Users\Rachid\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1038, in bootstrap_inner
self.run()
File "C:\Users\Rachid\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 975, in run
self._target(self._args, **self._kwargs)
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\utils\autoreload.py", line 64, in wrapper
fn(
args, **kwargs)
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\core\management\commands\runserver.py", line 133, in inner_run
self.check(display_num_errors=True)
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\core\management\base.py", line 485, in check
all_issues = checks.run_checks(
^^^^^^^^^^^^^^^^^^
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\core\checks\registry.py", line 88, in run_checks
new_errors = check(app_configs=app_configs, databases=databases)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\core\checks\urls.py", line 42, in check_url_namespaces_unique
all_namespaces = _load_all_namespaces(resolver)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\core\checks\urls.py", line 61, in _load_all_namespaces
url_patterns = getattr(resolver, "url_patterns", [])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\utils\functional.py", line 57, in __get_

res = instance.dict[self.name] = self.func(instance)
^^^^^^^^^^^^^^^^^^^
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
^^^^^^^^^^^^^^^^^^^
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\utils\functional.py", line 57, in get
res = instance.dict[self.name] = self.func(instance)
^^^^^^^^^^^^^^^^^^^
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module
return import_module(self.urlconf_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Rachid\AppData\Local\Programs\Python\Python311\Lib\importlib_init_.py", line 126, in import_module
return bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen importlib._bootstrap="">", line 1204, in _gcd_import
File "<frozen importlib._bootstrap="">", line 1176, in _find_and_load
File "<frozen importlib._bootstrap="">", line 1147, in _find_and_load_unlocked
File "<frozen importlib._bootstrap="">", line 690, in _load_unlocked
File "<frozen importlib._bootstrap_external="">", line 940, in exec_module
File "<frozen importlib._bootstrap="">", line 241, in _call_with_frames_removed
File "C:\Users\Rachid\Documents\Projets\Projets_Django\src_Outils\OutilsACO\urls.py", line 22, in <module>
from accounts.views import signup
File "C:\Users\Rachid\Documents\Projets\Projets_Django\src_Outils\accounts\views.py", line 8, in <module>
class CustomSignupForm(UserCreationForm):
File "C:\Users\Rachid\Documents\Projets\Projets_Django\env\Lib\site-packages\django\forms\models.py", line 321, in __new_</module></module></frozen></frozen></frozen></frozen></frozen></frozen>

raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (username) specified for CustomUser

C'est la première fois que j'obtiens ce message...</module></module></frozen></frozen></frozen></frozen></frozen></frozen>

Je viens de recréer un projet avec uniquement une application accounts, tout comme indiqué sur les vidéos et j'ai toujours ce message d'erreur :
django.core.exceptions.FieldError: Unknown field(s) (username) specified for CustomUser

Thibault houdon

Mentor

Est-ce que tu utilises le UserCreationForm quelque part dans ton code ?

Non, je ne l'utilise pas.

Voici le contenu de mon fichier accouts/models.py :
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager

from django.db import models

class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError("Vous devez entrer un email.")
user = self.model(email=self.normalize_email(email))
user.set_password(password)
user.save()
return user

def create_superuser(self, email,  password=None):
    user = self.create_user(email=email, password=password)
    user.is_admin = True
    user.is_staff = True
    user.save()
    return user

class CustomUser(AbstractBaseUser):
email = models.EmailField(
unique=True,
blank=False,
max_length=255
)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)

USERNAME_FIELD = "email"
objects = MyUserManager()

def has_perm(self, perm, obj=None):
    return True

def has_module_perms(self, app_label):
    return True

Je l'utilise dans le fichier accounts/views.py :

from django.http import HttpResponse
from django.shortcuts import render
from django.contrib.auth.forms import UserCreationForm

from accounts.models import CustomUser

class CustomSignupForm(UserCreationForm):
class Meta:
model = CustomUser
fields = UserCreationForm.Meta.fields

def signup(request):
context = {}
if request.method == "POST":
form = CustomSignupForm(request.POST)
if form.is_valid():
form.save()
return HttpResponse("Bienvenue !")
else:
context["errors"] = form.errors
form = CustomSignupForm()
context["form"] = form
return render(request, "accounts/signup.html", context=context)

Thibault houdon

Mentor

ok, je pense voir où est le souci :)

Le formulaire UserCreationForm par défaut de Django s'attend à ce qu'il y ait un champ username dans ton modèle d'utilisateur. Comme tu utilises ton propre modèle CustomUser qui n'a pas de champ username, tu obtiens cette erreur.

Dans ton formulaire CustomSignupForm, tu peux simplement remplacer UserCreationForm.Meta.fields par une liste des champs que tu souhaites inclure dans le formulaire. Par exemple, si tu veux juste l'email et le mot de passe, tu peux faire comme ceci :

class CustomSignupForm(UserCreationForm):
    class Meta:
        model = CustomUser
        fields = ['email', 'password1', 'password2']

Bonjour Thibault,
Merci pour ton retour. J'ai modifié la liste "fields" et ça fonctionne à présent !
Ca vaudrait peut-être le coup, quand tu auras le temps, de modifier la vidéo en conséquence de manière à ce que de futurs élèves ne rencontrent pas le même soucis lorsqu'ils suivront pas à pas la vidéo.
Bonne journée et merci encore.
Rachid.

Inscris-toi

(c'est gratuit !)

Inscris-toi

Tu dois créer un compte pour participer aux discussions.

Créer un compte

Rechercher sur le site

Formulaire de contact

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.