#python #django #django-models #django-forms
Вопрос:
Я создаю пользовательского пользователя Django с нуля. Почти все работает, но возникает проблема, когда я создаю нового пользователя из панели администратора Django следующим образом.
django.db.utils.IntegrityError: UNIQUE constraint failed: accounts_user.username
Почему возникает эта ошибка, даже если username
в моей модели нет поля User
?
Я включил сюда вспомогательные файлы.
models.py
import uuid
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import gettext_lazy as _
from .managers import CustomManager
from .utils import path_to_upload
# Create your models here.
class BaseModelMixin(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
creation_date = models.DateTimeField(_("Created At"), auto_now=True)
modification_date = models.DateTimeField(_("Modified At"),
auto_now_add=True)
class Meta:
abstract = True
class User(AbstractUser, BaseModelMixin):
display_name = models.CharField(_("Display Name"), max_length=200,
blank=True, null=True)
email = models.EmailField(_("Email Address"), unique=True,
blank=False, null=False)
profile_pic = models.ImageField(_("Profile Picture"),
upload_to=path_to_upload)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["display_name"]
objects = CustomManager()
forms.py
from django import forms
from django.contrib.auth.password_validation import validate_password
from django.forms import TextInput, PasswordInput
from django.contrib.auth.forms import UserCreationForm
from django.utils.translation import gettext_lazy as _
from .models import User
class AdminUserRegistrationForm(UserCreationForm):
password1 = forms.CharField(validators=[validate_password,],
widget=forms.PasswordInput(attrs={"placeholder": "Password"}))
password2 = forms.CharField(validators=[validate_password, ],
widget=forms.PasswordInput(attrs={"placeholder": "Confirm Password"}))
class Meta(UserCreationForm.Meta):
model = User
fields = ["display_name", "email", "profile_pic"]
widgets = {}
for field in fields:
if field not in ("password", "profile_pic"):
widgets[field] = TextInput(attrs={
"placeholder": field.replace("_", " ").title()
})
widgets["password"] = PasswordInput(render_value=True,
attrs={'required': False})
widgets["profile_pic"] = forms.FileInput()
class AdminUserUpdateForm(forms.ModelForm):
password = forms.CharField(label=_("Password"), required=True,
validators=[validate_password],
widget=PasswordInput(render_value=True))
class Meta:
model = User
fields = ["display_name", "profile_pic", "password"]
widgets = {}
for field in fields:
if not field == "profile_pic":
widgets[field] = TextInput(attrs={"placeholder": field.replace("_", " ").title()})
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
managers.py
from django.contrib.auth.models import BaseUserManager
from django.utils.translation import gettext_lazy as _
class CustomManager(BaseUserManager):
def create_user(self, display_name, email, password, **extras):
if not email:
raise ValueError(_("Email is a mandatory field"))
email = self.normalize_email(email)
user = self.model(display_name=display_name, email=email, **extras)
user.set_password(password)
# user.save()
return user
def create_superuser(self, display_name, email, password, **extras):
extras.setdefault("is_staff", True)
extras.setdefault("is_active", True)
extras.setdefault("is_superuser", True)
if "is_superuser" not in extras:
raise ValueError(_("'is_superuser' is mandatory for superuser"))
if "is_staff" not in extras:
raise ValueError(_("'is_staff' is mandatory for superuser"))
return self.create_user(display_name, email, password, **extras)
admin.py
from django.contrib import admin
from . import models
from . import forms
# Register your models here.
class CustomUserAdmin(admin.ModelAdmin):
# add_form = forms.AdminUserRegistrationForm
form = forms.AdminUserRegistrationForm
model = models.User
list_display_links = None
list_display = ("display_name", "email",)
admin.site.register(models.User, CustomUserAdmin)
Ответ №1:
Вы наследуете от AbstractBaseUser
, и у него есть username
поле, чтобы полностью удалить его из вашей модели, вам нужно установить его как None
в пользовательском классе пользователя:
class User(AbstractUser, BaseModelMixin):
username = None
...
Комментарии:
1. Это устранило эту ошибку, но привело к новой. Теперь это говорит
NOT NULL constraint failed: accounts_user.username
само за себя . Какое это имеет отношениеusername
, если об этом даже не упоминается.2. вы бежали
makemigrations
иmigrate
после удаления поля?
Ответ №2:
По умолчанию AbstractUser
имеет username
поле.
при этом поле имени USERNAME_FIELD = "email"
пользователя не будет удалено.
Он просто говорит Django использовать email
в качестве поля имени пользователя вместо фактического username
поля.
поскольку username
поле является обязательным и уникальным, вам необходимо удалить его вручную:
class User(AbstractUser, BaseModelMixin):
# ...
username = None
# ...