Начал работать с Django относительно недавно, сделал все тестовые проекты (как официальный Django, так и несколько проектов с YouTube). Сейчас решил сделать портал для музыкальной школы знакомых. Нужно сделать кастомную систему аутентификации, основанную на номере телефона и случайно сгенерированном пароле, который будет отсылаться при регистрации на номер телефона.
Написал AbsractBaseUser, кастомный менеджер, формы, на создании всё ок - пароль генерится и сохраняется. Но при попытке изменить чью либо учётку - выкидывает ошибку
IntegrityError: NOT NULL constraint failed: accounts_user.password
Не знаю, где прокололся, подскажите, пожалуйста :)
Models.py:
class UserManager(BaseUserManager):
use_in_migrations = True
def create_user(self, phone, first_name, last_name, country, city, **extra_fields):
if not phone:
raise ValueError('Пользователь должен иметь номер телефона')
if not first_name:
raise ValueError('У пользователя должно быть имя')
if not last_name:
raise ValueError('У пользователя должна быть фамилия')
user = self.model(
phone=phone,
first_name=first_name,
last_name=last_name,
country=country,
city=city,
**extra_fields,
)
password = User.objects.make_random_password(length=12)
print (password)
user.set_password(password)
user.save(using=self._db)
return user
def create_tutor(self, phone, first_name, last_name, country, city, **extra_fields):
user = self.create_user(
phone=phone,
first_name=first_name,
last_name=last_name,
country=country,
city=city,
**extra_fields,
)
user.is_tutor = True
user.save(using=self._db)
return user
def create_superuser(self, phone, first_name, last_name, country, city, **extra_fields):
user = self.create_user(
phone=phone,
first_name=first_name,
last_name=last_name,
country=country,
city=city,
**extra_fields,
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
phone = models.CharField(
verbose_name='Телефон',
max_length=16,
unique=True,
)
recieves_sms = models.BooleanField(
verbose_name='Подписан на СМС рассылку',
default=True,
)
first_name = models.CharField(
verbose_name='Имя',
max_length=50,
)
last_name = models.CharField(
verbose_name='Фамилия',
max_length=50,
)
country = models.CharField(
verbose_name='Страна',
max_length=50,
)
city = models.CharField(
verbose_name='Город',
max_length=50,
)
attached_tutor = models.ForeignKey(
'self',
verbose_name='Привязанный преподаватель',
on_delete=models.SET_NULL,
blank=True,
null=True,
)
COURSE_CHOICES = (
('F', 'Очная'),
('D', 'Заочная'),
('O', 'Удалённая'),
('N', 'Никакая'),
)
course = models.CharField(
verbose_name='Форма обучения',
max_length=1,
choices=COURSE_CHOICES,
default='N',
)
RATING_CHOICES = (
('1', 'Очень низкий'),
('2', 'Низкий'),
('3', 'Средний'),
('4', 'Высокий'),
('5', 'Очень высокий'),
)
rating = models.CharField(
verbose_name='Рейтинг',
max_length=1,
choices=RATING_CHOICES,
default='3',
)
is_active = models.BooleanField(
verbose_name='Активен',
default=True,
)
is_tutor = models.BooleanField(
verbose_name='Преподаёт',
default=False,
)
is_admin = models.BooleanField(
verbose_name='Администрирует',
default=False,
)
objects = UserManager()
USERNAME_FIELD = 'phone'
REQUIRED_FIELDS = ['first_name', 'last_name', 'country', 'city']
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
@property
def is_staff(self):
return self.is_admin
admin.py:
from accounts.models import User
class UserCreationForm(forms.ModelForm):
class Meta:
model = User
fields = (
'phone',
'first_name',
'last_name',
'country',
'city',
)
def save(self, commit=True):
user = super().save(commit=False)
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = (
'phone',
'recieves_sms',
'first_name',
'last_name',
'country',
'city',
'attached_tutor',
'course',
'rating',
)
class UserAdmin(BaseUserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = (
'phone',
'recieves_sms',
'first_name',
'last_name',
'country',
'city',
'attached_tutor',
'course',
'rating',
)
list_filter = ('is_admin', 'is_tutor',)
fieldsets = (
(None, {'fields': ('phone', 'password', 'recieves_sms')}),
('Личные данные', {'fields': ('first_name', 'last_name', 'country', 'city')}),
('Обучение', {'fields': ('attached_tutor', 'course', 'rating')}),
('Права доступа', {'fields': ('is_admin', 'is_tutor')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': (
'phone',
'first_name',
'last_name',
'country',
'city'
)}
),
)
search_fields = ('phone', 'first_name', 'last_name',)
ordering = ('first_name', 'last_name',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
admin.site.unregister(Group)

Заранее - огромное спасибо!