Изменить отношение наследования к OneToOne‍ в моделях Django - PullRequest
2 голосов
/ 25 апреля 2020

У меня есть модели с 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

1 Ответ

0 голосов
/ 26 апреля 2020

говорит, что у вас уже есть поле с именем "create_date" в модели User. Вам не нужно добавлять их снова в модель учителя и ученика.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...