[英]How can I merge different Db Models into one?
I have an old Django Project, which I started when I was a beginner.我有一个旧的 Django 项目,我是初学者时就开始的。 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:新模型.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?我的问题是:是否可以将我的旧项目(我已经有两个客户在使用旧项目)适应这个新品牌类型的数据库 model?
I would do this with the following steps:我将通过以下步骤执行此操作:
The same can be done for the Instructor model可以对 Instructor model 执行相同的操作
I'll give an example for step 3 here:我将在这里给出第 3 步的示例:
## 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)
]
Maybe what you are looking for are Proxy models: https://docs.djangoproject.com/en/4.1/topics/db/models/#proxy-models也许你正在寻找的是代理模型: https://docs.djangoproject.com/en/4.1/topics/db/models/#proxy-models
From docs: This is what proxy model inheritance is for: creating a proxy for the original model. You can create, delete and update instances of the proxy model and all the data will be saved as if you were using the original (non-proxied) model. The difference is that you can change things like the default model ordering or the default manager in the proxy, without having to alter the original.
来自文档:
This is what proxy model inheritance is for: creating a proxy for the original model. You can create, delete and update instances of the proxy model and all the data will be saved as if you were using the original (non-proxied) model. The difference is that you can change things like the default model ordering or the default manager in the proxy, without having to alter the original.
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
# ...
pass
The MyPerson class operates on the same database table as its parent Person class. In particular, any new instances of Person will also be accessible through MyPerson, and vice-versa
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.