M2MフィールドをForeignKeyフィールドに変更しようとしています。コマンドvalidateで問題が表示されず、syncdbを実行すると:
ValueError: Cannot alter field xxx into yyy they are not compatible types (you cannot alter to or from M2M fields, or add or remove through= on M2M fields)
したがって、移行を行うことはできません。
class InstituteStaff(Person):
user = models.OneToOneField(User, blank=True, null=True)
investigation_area = models.ManyToManyField(InvestigationArea, blank=True,)
investigation_group = models.ManyToManyField(InvestigationGroup, blank=True)
council_group = models.ForeignKey(CouncilGroup, null=True, blank=True)
#profiles = models.ManyToManyField(Profiles, null = True, blank = True)
profiles = models.ForeignKey(Profiles, null = True, blank = True)
これは私の最初のDjangoプロジェクトなので、どんな提案でも歓迎します。
私はこれにつまずいて、自分のデータについてはあまり気にしませんでしたが、DB全体を削除したくはありませんでした。そこで、移行ファイルを開いて、AlterField()
コマンドをRemoveField()
およびAddField()
コマンドに変更して、うまく機能するようにしました。特定のフィールドでデータを失いましたが、それ以外は何も失いませんでした。
つまり.
migrations.AlterField(
model_name='player',
name='teams',
field=models.ManyToManyField(related_name='players', through='players.TeamPlayer', to='players.Team'),
),
に
migrations.RemoveField(
model_name='player',
name='teams',
),
migrations.AddField(
model_name='player',
name='teams',
field=models.ManyToManyField(related_name='players', through='players.TeamPlayer', to='players.Team'),
),
潜在的な回避策:
profiles1
というForeignKey関係を持つ新しいフィールドを作成し、profiles
を変更しないでください。移行を作成して実行します。競合を防ぐために、related_name
パラメーターが必要になる場合があります。元のフィールドを削除する後続の移行を実行します。次に、profiles1
の名前をprofiles
に戻す別の移行を実行します。明らかに、新しいForeignKeyフィールドにはデータがありません。
カスタム移行を作成します: https://docs.djangoproject.com/en/1.7/ref/migration-operations/
makemigration
ではなく、migration
とsyncdb
を使用することもできます。
InstituteStaff
には保持するデータがありますか?
私は言うだろう:マシンが私たちのために何かをすることができない場合、それを助けましょう!
OPがここに置いた問題には複数の突然変異が含まれている可能性があるため、この種の問題と闘う方法を簡単に説明しようとします。
次のようなモデル(users
というアプリ内)があると仮定します。
from Django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person)
def __str__(self):
return self.name
しばらくしてから、メンバー参加の日付を追加する必要があります。だからこれが欲しい:
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership') # <-- through model
def __str__(self):
return self.name
# and through Model itself
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
さて、通常はOPが書いたのと同じ問題にぶつかります。それを解決するには、次の手順を実行します。
この時点から開始します。
from Django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person)
def __str__(self):
return self.name
モデルを作成してpython manage.py makemigrations
(を実行しますが、Group.members
フィールドにthrough
プロパティをまだ入れないでください ):
from Django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person) # <-- no through property yet!
def __str__(self):
return self.name
class Membership(models.Model): # <--- through model
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
python makemigrations users --empty
コマンドを使用して空の移行を作成し、変換スクリプトをpythonで作成します(python migrations here )の詳細)古いフィールド(Group.members
)の新しい関係(Membership
)を作成します。次のようになります。
# Generated by Django A.B on YYYY-MM-DD HH:MM
import datetime
from Django.db import migrations
def create_through_relations(apps, schema_editor):
Group = apps.get_model('users', 'Group')
Membership = apps.get_model('users', 'Membership')
for group in Group.objects.all():
for member in group.members.all():
Membership(
person=member,
group=group,
date_joined=datetime.date.today()
).save()
class Migration(migrations.Migration):
dependencies = [
('myapp', '0005_create_models'),
]
operations = [
migrations.RunPython(create_through_relations, reverse_code=migrations.RunPython.noop),
]
members
モデルのGroup
フィールドを削除してpython manage.py makemigrations
を実行すると、Group
は次のようになります。
class Group(models.Model):
name = models.CharField(max_length=128)
members
フィールドにGroup
モデルを追加しますが、今はthrough
プロパティを使用してpython manage.py makemigrations
を実行します。
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
以上です!
ここで、モデル内で、コードの新しい方法でメンバーの作成を変更する必要があります。 こちら の詳細。
squashing これらの移行により、オプションで整理することもできます。
まだアプリケーションを開発していて、既存のデータを保存する必要がない場合は、次の方法でこの問題を回避できます。
データベースを削除して再作成します。
project/app/migrationsフォルダーに移動します
init。pyファイルを除き、そのフォルダー内のすべてを削除します。 pycachedirも必ず削除してください。
Syncdb、makemigrations、および移行を実行します。