У меня есть модели с inheritance relationship
. Я хочу превратить это отношение в отношение OneToOne
, без удаления каких-либо данных в проекте.
Это структура моделей:
class BaseFieldsModel(models.Model):
create_date = DateTimeField(auto_now_add=True,)
update_date = DateTimeField(auto_now=True,)
created_by = ForeignKey('UserManager.User', related_name='created_%(class)ss')
updated_by = ForeignKey('UserManager.User', related_name='updated_%(class)ss')
class User(AbstractBaseUser,BaseFieldsModel):
# Some fields
class Teacher(User):
# Some fields
class Student(User):
# Some fields
Все было хорошо, пока я не хочу реструктурировать свою базу данных из-за этой проблемы, которая была у меня в этом дизайне. В новой модели БД я хочу получить что-то вроде этого: (OneToOne Relation)
class User(AbstractBaseUser,BaseFieldsModel):
# Some fields
class Teacher(BaseFieldsModel):
user_ptr = OneToOneField('UserManager.User', primary_key=True,related_name='student_user')
# Some fields
class Student(BaseFieldsModel):
user_ptr = OneToOneField('UserManager.User', primary_key=True,related_name='teacher_user')
# Some fields
Итак, я запустил makemigrations
:
Migrations for 'UserManager':
UserManager/migrations/0022_auto_20200425_1233.py
- Change managers on student
- Change managers on teacher
- Add field create_date to student
- Add field created_by to student
- Add field update_date to student
- Add field updated_by to student
- Add field create_date to teacher
- Add field created_by to teacher
- Add field update_date to teacher
- Add field updated_by to teacher
- Alter field user_ptr on student
- Alter field user_ptr on teacher
, а затем запустил migrate
и получил эту ошибку:
django.core.exceptions.FieldError: Local field 'create_date' in class 'Student' clashes with field of the same name from base class 'User'.
# Протестированные решения
1.Первое неудачное решение:
Создать Teacher
и Student
без формы наследования BaseFielsModel
:
class User(AbstractBaseUser,BaseFieldsModel):
# Some fields
class Teacher(models.Model):
user_ptr = OneToOneField('UserManager.User', primary_key=True,related_name='student_user')
create_date = DateTimeField(auto_now_add=True,)
update_date = DateTimeField(auto_now=True,)
created_by = ForeignKey('UserManager.User', related_name='created_%(class)ss')
updated_by = ForeignKey('UserManager.User', related_name='updated_%(class)ss')
# Some other fields
class Student(models.Model):
user_ptr = OneToOneField('UserManager.User', primary_key=True,related_name='teacher_user')
create_date = DateTimeField(auto_now_add=True,)
update_date = DateTimeField(auto_now=True,)
created_by = ForeignKey('UserManager.User', related_name='created_%(class)ss')
updated_by = ForeignKey('UserManager.User', related_name='updated_%(class)ss')
# Some other fields
Затем выполните makemigrations
:
Migrations for 'UserManager':
UserManager/migrations/0022_auto_20200425_1240.py
- Change managers on student
- Change managers on teacher
- Add field create_date to student
- Add field created_by to student
- Add field update_date to student
- Add field updated_by to student
- Add field create_date to teacher
- Add field created_by to teacher
- Add field update_date to teacher
- Add field updated_by to teacher
- Alter field user_ptr on student
- Alter field user_ptr on teacher
Затем migrate
и снова выдайте ошибку:
django.core.exceptions.FieldError: Local field 'create_date' in class 'Student' clashes with field of the same name from base class 'User'.
2. Второе неудачное решение:
Создать Teacher
и Student
без BaseFielsModel
и его полей:
class User(AbstractBaseUser,BaseFieldsModel):
# Some fields
class Teacher(models.Model):
user_ptr = OneToOneField('UserManager.User', primary_key=True,related_name='student_user')
# Some other fields
class Student(models.Model):
user_ptr = OneToOneField('UserManager.User', primary_key=True,related_name='teacher_user')
# Some other fields
Затем выполнить makemigrations
:
Migrations for 'UserManager':
UserManager/migrations/0022_auto_20200425_1243.py
- Change managers on student
- Change managers on teacher
- Alter field user_ptr on student
- Alter field user_ptr on teacher
и запустите migrate
:
Applying UserManager.0022_auto_20200425_1243... OK
Затем добавьте эти поля в Student
и Teacher
:
create_date = DateTimeField(auto_now_add=True,)
update_date = DateTimeField(auto_now=True,)
created_by = ForeignKey('UserManager.User', related_name='created_%(class)ss')
updated_by = ForeignKey('UserManager.User', related_name='updated_%(class)ss')
Затем запустите makemigrations
:
Migrations for 'UserManager':
UserManager/migrations/0023_auto_20200425_1245.py
- Add field create_date to student
- Add field created_by to student
- Add field update_date to student
- Add field updated_by to student
- Add field create_date to teacher
- Add field created_by to teacher
- Add field update_date to teacher
- Add field updated_by to teacher
И migrate
:
django.core.exceptions.FieldError: Local field 'create_date' in class 'Student' clashes with field of the same name from base class 'User'.
3. Третье успешное решение (плохая практика)
Переименовать все поля с полями sh с полями в User
модели:
class User(AbstractBaseUser,BaseFieldsModel):
# Some fields
class Teacher(models.Model):
user_ptr = OneToOneField('UserManager.User', primary_key=True,related_name='student_user')
teacher_create_date = DateTimeField(auto_now_add=True,)
teacher_update_date = DateTimeField(auto_now=True,)
teacher_created_by = ForeignKey('UserManager.User', related_name='created_%(class)ss')
teacher_updated_by = ForeignKey('UserManager.User', related_name='updated_%(class)ss')
# Some other fields
class Student(models.Model):
user_ptr = OneToOneField('UserManager.User', primary_key=True,related_name='teacher_user')
student_create_date = DateTimeField(auto_now_add=True,)
student_update_date = DateTimeField(auto_now=True,)
student_created_by = ForeignKey('UserManager.User', related_name='created_%(class)ss')
student_updated_by = ForeignKey('UserManager.User', related_name='updated_%(class)ss')
# Some other fields
Затем makemigrations
:
Migrations for 'UserManager':
UserManager/migrations/0023_auto_20200425_1335.py
- Add field student_create_date to student
- Add field student_created_by to student
- Add field student_update_date to student
- Add field student_updated_by to student
- Add field teacher_create_date to teacher
- Add field teacher_created_by to teacher
- Add field teacher_update_date to teacher
- Add field teacher_updated_by to teacher
и, наконец, migrate
:
Applying UserManager.0023_auto_20200425_1335... OK
И готово!
Что не так с Django? XD