亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在保留數據的同時將 Django 外鍵移動到另一個模型?

在保留數據的同時將 Django 外鍵移動到另一個模型?

叮當貓咪 2023-06-20 13:50:45
我有一個 Django 應用程序,其中有一個基本用戶模型和用戶配置文件模型。class Office(models.Model):    name = models.CharField()class User(models.Model):    email = models.EmailField()    offices = models.ManyToManyField(Office)class Profile(models.Model):    user = models.OneToOneField(User)每個用戶都有一個配置文件,可以分配給許多不同的辦公室。我想要做的是擁有它,以便用戶可以擁有多個配置文件,但配置文件可以分配給不同的辦公室。目前,這是不可能的,因為 Office 字段是在用戶級別而不是配置文件級別分配的。我設想了 2 種方法來解決這個問題:想辦法將該offices字段移到配置文件字段。創建一個新模型,其中ProfileNoUser包含用戶模型的外鍵以及offices其中的外鍵。您認為哪個選項最好?如果#1,我該怎么做?
查看完整描述

1 回答

?
Cats萌萌

TA貢獻1805條經驗 獲得超9個贊

您的問題是關于數據遷移嗎?

如果是這樣,您應該閱讀鏈接的文檔。

在我看來,您的第一個提案確實是最好的。

這是如何做的。

第 1 步:對模型進行更改

您更改模型以匹配您的目標:

# models.py


from django.db import models


class Office(models.Model):

? ? name = models.CharField(max_length=1000)


class User(models.Model):

? ? email = models.EmailField()


class Profile(models.Model):

? ? user = models.OneToOneField(User, on_delete=models.CASCADE)

? ? offices = models.ManyToManyField(Office)

運行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 步:編輯遷移文件以遷移現有數據

打開上一步創建的文件。它看起來像:


# Generated by Django 3.1 on 2020-08-25 13:11


from django.db import migrations, models



class Migration(migrations.Migration):


? ? dependencies = [

? ? ? ? ('so', '0001_initial'),

? ? ]


? ? operations = [

? ? ? ? migrations.RemoveField(

? ? ? ? ? ? model_name='user',

? ? ? ? ? ? name='offices',

? ? ? ? ),

? ? ? ? migrations.AddField(

? ? ? ? ? ? model_name='profile',

? ? ? ? ? ? name='offices',

? ? ? ? ? ? field=models.ManyToManyField(to='so.Office'),

? ? ? ? ),

? ? ]

你需要在這里做兩件事:


您可以看到,對于 Django 生成的命令,它將首先刪除舊的 FK,然后添加新的。你應該改變它,所以它是相反的。

然后你將不得不編寫一些 python 代碼,遷移將在正確的時間執行

正確的時間是在創建新 FK 之后和舊 FK 被刪除之前,這樣您就可以訪問這兩個 FK 來遷移數據:


# Generated by Django 3.1 on 2020-08-25 13:11


from django.db import migrations, models


def migrate_office_to_profile(apps, schema_editor):

? ? User = apps.get_model('so', 'User')

? ? for user in User.objects.all():

? ? ? ? for office in user.office_set:

? ? ? ? ? ? user.profile.add(office)


def migrate_office_to_user(apps, schema_editor):

? ? Profile = apps.get_model('so', 'Profile')

? ? for profile in Profile.objects.all():

? ? ? ? profile.user.add(profile.offices)

? ? ? ? for office in profile.office_set:

? ? ? ? ? ? profile.user.add(office)


class Migration(migrations.Migration):

? ? dependencies = [

? ? ? ? ('so', '0001_initial'),

? ? ]


? ? operations = [

? ? ? ? migrations.AddField(

? ? ? ? ? ? model_name='profile',

? ? ? ? ? ? name='offices',

? ? ? ? ? ? field=models.ManyToManyField(to='so.Office'),

? ? ? ? ),

? ? ? ? # This is where your python code will be called

? ? ? ? migrations.RunPython(

? ? ? ? ? ? # This is called in the forward migration

? ? ? ? ? ? migrate_office_to_profile,

? ? ? ? ? ? # This is called in the backward migration

? ? ? ? ? ? reverse_code=migrate_office_to_user

? ? ? ? ),

? ? ? ? migrations.RemoveField(

? ? ? ? ? ? model_name='user',

? ? ? ? ? ? name='offices',

? ? ? ? ),

? ? ]

我還沒有在真實數據上測試過這個。這是你的部分。


第 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 自動處理,但是對于數據遷移,您必須編寫給migrations.RunPython.


查看完整回答
反對 回復 2023-06-20
  • 1 回答
  • 0 關注
  • 131 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號