Python 在保留数据的同时将Django外键移动到另一个模型?
我有一个Django应用程序,其中有一个基本的用户模型和用户配置文件模型Python 在保留数据的同时将Django外键移动到另一个模型?,python,django,Python,Django,我有一个Django应用程序,其中有一个基本的用户模型和用户配置文件模型 班级办公室(models.Model): name=models.CharField() 类用户(models.Model): email=models.EmailField() 办公室=模型。多个多个字段(办公室) 类配置文件(models.Model): 用户=模型。OneToOneField(用户) 每个用户都有一个配置文件,可以分配到许多不同的办公室 我想做的是拥有它,这样一个用户可以有许多配置文件,但配置文件可
班级办公室(models.Model):
name=models.CharField()
类用户(models.Model):
email=models.EmailField()
办公室=模型。多个多个字段(办公室)
类配置文件(models.Model):
用户=模型。OneToOneField(用户)
每个用户都有一个配置文件,可以分配到许多不同的办公室
我想做的是拥有它,这样一个用户可以有许多配置文件,但配置文件可以分配到不同的办公室
目前,这是不可能的,因为Office字段是在用户级别而不是配置文件级别分配的。我设想了两种解决方法:
offices
字段移到Profile字段
ProfileNoUser
的思路创建一个新的模型,该模型具有用户模型的外键,并且具有offices
外键
#models.py
从django.db导入模型
班级办公室(models.Model):
name=models.CharField(最大长度=1000)
类用户(models.Model):
email=models.EmailField()
类配置文件(models.Model):
user=models.OneToOneField(用户,on_delete=models.CASCADE)
办公室=模型。多个多个字段(办公室)
运行makemigrations
:
(.venv) ~/c/s/m/mysite> ./manage.py makemigrations
Migrations for 'so':
so/migrations/0002_auto_20200825_1311.py
- Remove field offices from user
- Add field offices to profile
步骤2:编辑迁移文件以迁移现有数据
打开上一步创建的文件。它将看起来像:
#由Django 3.1于2020-08-25 13:11生成
从django.db导入迁移、模型
类迁移(migrations.Migration):
依赖项=[
(‘so’、‘0001_首字母’),
]
操作=[
migrations.RemoveField(
型号_name='user',
办公室名称,
),
migrations.AddField(
型号_name='profile',
办公室名称,
field=models.ManyToManyField(to='so.Office'),
),
]
在这里,您需要做两件事:
- 您可以看到,对于Django生成的订单,它将首先删除旧的FK,然后添加新的FK。你应该改变这一点,让它成为另一种方式
- 然后,您必须编写一些python代码,以便在正确的时间执行迁移
#由Django 3.1于2020-08-25 13:11生成
从django.db导入迁移、模型
def将办公室迁移到配置文件(应用程序、架构编辑器):
User=apps.get_model('so','User'))
对于user.objects.all()中的用户:
对于user.office\u集合中的office:
user.profile.add(办公室)
def将办公室迁移到用户(应用程序、架构编辑器):
Profile=apps.get_model('so','Profile'))
对于profile.objects.all()中的概要文件:
profile.user.add(profile.offices)
对于profile.office\u集合中的office:
profile.user.add(办公室)
类迁移(migrations.Migration):
依赖项=[
(‘so’、‘0001_首字母’),
]
操作=[
migrations.AddField(
型号_name='profile',
办公室名称,
field=models.ManyToManyField(to='so.Office'),
),
#这就是调用python代码的地方
migrations.RunPython(
#这称为正向迁移
将办公室迁移到配置文件,
#这称为向后迁移
反向代码=将办公室迁移到用户
),
migrations.RemoveField(
型号_name='user',
办公室名称,
),
]
我还没有在真实数据上测试过这一点。这是你的职责。
步骤3:运行并调试迁移
制作数据库的副本,运行迁移,并查看迁移过程:
(.venv) ~/c/s/m/mysite> ./manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, so
Running migrations:
Applying so.0002_auto_20200825_1311... OK
处理数据迁移时,应始终编写并调试反向迁移:
(.venv) ~/c/s/m/mysite> ./manage.py migrate so 0001
Operations to perform:
Target specific migration: 0001_initial, from so
Running migrations:
Rendering model states... DONE
Unapplying so.0002_auto_20200825_1311... OK
请记住,迁移文件已添加到版本控制中,并且是软件的一部分
==编辑===
阐明反向或反向迁移的概念
Django迁移通常只以一种方式运行:增加迁移数量
但是,尽管在开发过程中可能会进行各种测试和仔细思考,但您不能总是考虑生产数据。代码“简单”,因为它在生产环境中与在开发服务器上的代码相同。但生产数据通常是不同的
Django迁移在部署期间可能会失败。例如,因为您正在添加一个您认为只能为真的显式唯一约束。但不知何故,对于生产数据,迁移将导致完整性错误
然后,您将被困在完成了一半的迁移和没有迁移就无法运行的新代码中。如果您花时间确保迁移可以向前运行和向后运行而不丢失数据,则可以安全地撤消迁移并恢复到以前的代码,然后返回以找出错误所在,而不必当场修复
Django会自动为模型结构处理向前和向后迁移,但对于数据迁移,您必须编写为
迁移提供的函数。运行Python
,以便用户可以为每个办公室创建一个配置文件?因此,它是m2m关系A中的“中间”表