Erreur lors de la création des 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
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"
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>
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)
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 !)
Tu dois créer un compte pour participer aux discussions.
Créer un compte