I have an old Django Project, which I started when I was a beginner. So far it worked but, due to some code refactoring I would like to do, I would like to change the original database models. Basically, I originally made many different models, each one for a user type.
old models:
class CustomUser(AbstractUser):
user_type_data = (
('admin', 'Admin'),
('instructor', 'Instructor'),
('student', 'Student'),
('renter', 'Renter'),
)
user_type = models.CharField(
max_length=20, choices=user_type_data, default=1)
class Admin(models.Model):
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
date_of_birth = models.DateField(null=True, blank=True)
fiscal_code = models.CharField(max_length=50, null=True, blank=True)
phone = models.CharField(max_length=50, null=True, blank=True)
picture = models.ImageField(
blank=True, null=True, default='default.png')
address = models.CharField(max_length=100, blank=True, null=True)
cap = models.CharField(max_length=10, blank=True, null=True)
city = models.CharField(max_length=100, blank=True, null=True)
province = models.CharField(
max_length=100, choices=PROVINCE_CHOICES, blank=True, null=True)
country = CountryField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.user.username
class Meta:
ordering = ['last_name']
class Instructor(models.Model):
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
date_of_birth = models.DateField(null=True, blank=True)
fiscal_code = models.CharField(max_length=50, null=True, blank=True)
phone = models.CharField(max_length=50, null=True, blank=True)
picture = models.ImageField(
blank=True, null=True, default='default.png')
address = models.CharField(max_length=100, null=True, blank=True)
cap = models.CharField(max_length=10, null=True, blank=True)
city = models.CharField(max_length=100, null=True, blank=True)
province = models.CharField(
max_length=100, choices=PROVINCE_CHOICES, blank=True, null=True)
country = CountryField(blank=True, null=True)
is_active = models.BooleanField(default=True)
flight_wage = models.FloatField(null=True, blank=True)
theory_wage = models.FloatField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.user.last_name + ' ' + self.user.first_name
class Meta:
ordering = ['last_name']
I posted just the first two user type but you get the picture. A lot of redundant code. What I would like to achieve is something like that:
new models.py:
class CustomUser(AbstractUser):
user_type_data = (
('admin', 'Admin'),
('instructor', 'Instructor'),
('student', 'Student'),
('renter', 'Renter'),
)
user_type = models.CharField(
max_length=20, choices=user_type_data, default=1)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
date_of_birth = models.DateField(null=True, blank=True)
fiscal_code = models.CharField(max_length=50, null=True, blank=True)
phone = models.CharField(max_length=50, null=True, blank=True)
picture = models.ImageField(
blank=True, null=True, default='default.png')
address = models.CharField(max_length=100, null=True, blank=True)
cap = models.CharField(max_length=10, null=True, blank=True)
city = models.CharField(max_length=100, null=True, blank=True)
province = models.CharField(
max_length=100, choices=PROVINCE_CHOICES, blank=True, null=True)
country = CountryField(blank=True, null=True)
is_active = models.BooleanField(default=True)
flight_wage = models.FloatField(null=True, blank=True)
theory_wage = models.FloatField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.user.last_name + ' ' + self.user.first_name
class Meta:
ordering = ['last_name']
My question is: Is it possibile to adapt my old projects (I already have two customers using the old project) to this new brand type of database model?
I would do this with the following steps:
The same can be done for the Instructor model
I'll give an example for step 3 here:
## Example migration file
from django.db import migrations
def add_values_to_user(apps, schema):
CustomUser = apps.get_model('users', 'CustomUser')
for user in CustomUser.objects.all():
if user.admin:
user.first_name = user.admin.first_name
elif user.instructor:
user.first_name = user.instructor.first_name
# Do this for all values you require for the admin and instructor model
user.save()
class Migration(migrations.Migration):
dependencies = [
('users', '0046_auto_20220506_1523'),
]
operations = [
migrations.RunPython(add_values_to_user)
]