[英]Django trying to add an existing field when making a model managed
在管理 model 時,如何阻止 Django 2.2.4 嘗試創建已經存在的數據庫列?
我有 2 個模型,票證和消息,它們連接到第三方數據庫中的表,因此模型是使用managed=False
創建的。 我正在遠離第三方工具。 票證 model 不久前被其他人更改為managed=True
,現在我正在嘗試對消息 model 執行相同的操作。
這些是 model 的相關部分:
from django.db import models
class Message(models.Model):
mid = models.BigAutoField(db_column='MID', primary_key=True)
ticket = models.ForeignKey('Ticket', on_delete=models.CASCADE, db_column='TID')
author = models.CharField(db_column='AUTHOR', max_length=32)
date = models.DateTimeField(db_column='DATE')
internal = models.CharField(db_column='INTERNAL', max_length=1)
isoper = models.CharField(db_column='ISOPER', max_length=1)
headers = models.TextField(db_column='HEADERS')
msg = models.TextField(db_column='MSG')
class Meta:
# managed = False
db_table = 'messages'
permissions = (
("can_change_own_worked_time", "Can change own worked time"),
("can_change_own_recently_worked_time", "Can change own recently worked time"),
("can_change_subordinate_worked_time", "Can change subordinate worked time"),
)
這是通過注釋掉managed=False
生成的遷移:
# Generated by Django 2.2.4 on 2020-06-18 20:56 (0017_auto_20200618_1656)
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('troubleticket', '0016_auto_20200511_1644'),
]
operations = [
migrations.AlterModelOptions(
name='message',
options={'permissions': (('can_change_own_worked_time', 'Can change own worked time'), ('can_change_own_recently_worked_time', 'Can change own recently worked time'), ('can_change_subordinate_worked_time', 'Can change subordinate worked time'))},
),
]
# Generated by Django 2.2.4 on 2020-06-18 21:14 (0018_message_ticket)
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('troubleticket', '0017_auto_20200618_1656'),
]
operations = [
migrations.AddField(
model_name='message',
name='ticket',
field=models.ForeignKey(db_column='TID', default=1, on_delete=django.db.models.deletion.CASCADE, to='troubleticket.Ticket'),
preserve_default=False,
),
]
當我嘗試應用這些遷移時,我收到此錯誤:
django.db.utils.OperationalError: (1060, "Duplicate column name 'TID'")
初始遷移不包括 TID 列,后續遷移也不包括任何后續遷移,所以我理解為什么 Django 認為這是一個新列。 但這不是一個新專欄(model 自從第一次提交給 git 回購以來就擁有它)所以我也明白為什么 MySQL 會拋出錯誤。
這是初始遷移:
# Generated by Django 2.0.8 on 2018-08-20 14:43 (0001_initial)
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Message',
fields=[
('mid', models.BigAutoField(db_column='MID', primary_key=True, serialize=False)),
('author', models.CharField(db_column='AUTHOR', max_length=32)),
('date', models.DateTimeField(db_column='DATE')),
('internal', models.CharField(db_column='INTERNAL', max_length=1)),
('isoper', models.CharField(db_column='ISOPER', max_length=1)),
('headers', models.TextField(db_column='HEADERS')),
('msg', models.TextField(db_column='MSG')),
],
options={
'managed': False,
'db_table': 'messages',
},
),
migrations.CreateModel(
name='Ticket',
fields=[
('id', models.BigIntegerField(db_column='ID', primary_key=True, serialize=False)),
('accesskey', models.CharField(db_column='ACCESSKEY', max_length=64)),
('open', models.DateTimeField(db_column='OPEN')),
('updated', models.DateTimeField(db_column='UPDATED')),
('closed', models.DateTimeField(db_column='CLOSED', null=True)),
('status', models.CharField(db_column='STATUS', max_length=3)),
('oper', models.CharField(db_column='OPER', max_length=32)),
('email', models.CharField(db_column='EMAIL', max_length=128)),
('name', models.CharField(db_column='NAME', max_length=128)),
('subject', models.CharField(db_column='SUBJECT', max_length=255)),
('lname', models.CharField(db_column='LNAME', max_length=50)),
('company', models.CharField(db_column='C0', max_length=255)),
('type', models.CharField(db_column='C1', max_length=255)),
('c2', models.CharField(db_column='C2', max_length=255)),
('c3', models.DecimalField(db_column='C3', decimal_places=2, max_digits=6)),
('c4', models.CharField(db_column='C4', max_length=255)),
('pending', models.CharField(db_column='C5', max_length=255)),
('c6', models.CharField(db_column='C6', max_length=255)),
('c7', models.CharField(db_column='C7', max_length=255)),
('c8', models.CharField(db_column='C8', max_length=255)),
('cc', models.CharField(db_column='C9', max_length=255)),
('grp', models.CharField(db_column='GRP', max_length=10)),
('item', models.CharField(db_column='ITEM', max_length=255)),
],
options={
'managed': False,
'db_table': 'tickets',
},
),
]
寫完評論后 2 秒,我想出了解決問題的方法。
當從另一個 ORM“遷移”到 Django 時,請始終考慮以下方面。 以下是我的順序建議,但我仍在學習如何使用 django 遷移,所以請記住這一點。
需要注意的是,在計算要添加或更改哪些列時,數據庫的實際內容與 django 無關。 這意味着,在 django 模型的初始遷移中, managed
仍然是=False
,列是由 django “創建”和注冊的。 當 makemigrations 計算要添加哪些列時,它只將初始遷移中提到的列作為給定。 不是數據庫的實際內容。
知道了這一點,我們現在可以 go 字段為字段並根據第 2 點決定每個字段。
現在,一般來說,當設置 Model managed=True 字段時,將分為 3 類。
2.1 該字段目前在model定義,數據庫中,也是在初始提交中。
對於這種情況,無需采取任何措施。
2.2 該字段目前在model定義,數據庫中,但不在初始提交中。
對於這種情況,必須將字段定義添加到原始初始遷移腳本中。 因此,migrations.CreateModel 調用可能如下所示:
...
('field_already_present', models.FloatField(blank=True, null=True)),
...
2.3 該字段當前在數據庫中,但不在model定義或初始提交中
如果 django 應用程序中不需要該字段,則可以省略該字段。 如果在某些時候需要它,則必須將其添加到 model 以及第一次初始遷移中。 這樣,django makemigrations 將不會嘗試創建該字段。
現在設置 managed=True 並進行遷移。 這樣做兩次! 第一次,makemigrations 會將 model 設置為 managed,然后它會添加初始提交中沒有的字段。
在此之后,model 可以被視為與正常創建和從頭開始管理的 django model 相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.