我正在尝试将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项目,欢迎任何建议。
答案 0 :(得分:52)
我偶然发现了这一点,虽然我并不关心我的数据,但我仍然不想删除整个数据库。所以我打开了迁移文件并将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'),
),
答案 1 :(得分:21)
潜在的解决方法:
使用名为profiles1
的ForeignKey关系创建一个新字段,不要修改profiles
。制作并运行迁移。您可能需要related_name
参数来防止冲突。执行后续迁移以删除原始字段。然后执行另一次迁移,将profiles1
重命名为profiles
。显然,您在新的ForeignKey字段中没有数据。
撰写自定义迁移:https://docs.djangoproject.com/en/1.7/ref/migration-operations/
您可能希望使用makemigration
和migration
而不是syncdb
。
您的InstituteStaff
是否包含您要保留的数据?
答案 2 :(得分:15)
如果您仍在开发应用程序,并且不需要保留现有数据,则可以通过执行以下操作来解决此问题:
删除并重新创建数据库。
转到您的项目/ app / migrations文件夹
删除该文件夹中的所有内容,但 init .py文件除外。确保您还删除 pycache 目录。
运行syncdb,makemigrations和migrate。
答案 3 :(得分:13)
我会说:如果机器无法为我们做点什么,那就让我们帮忙吧!
由于这里放置的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
(但请不要在through
字段中放置Group.members
属性):
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迁移here的更多信息),这将为旧字段创建新关系(Membership
) (Group.members
)。看起来可能像这样:
# 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')
就是这样!现在,您需要通过模型以新的方式在代码中更改成员的创建。有关here的更多信息。
答案 4 :(得分:1)
This link helps you resolve all problems related to this 对我有用的是python3 backend / manage.py migration --fake“ app_name”
答案 5 :(得分:1)
另一种对我有用的方法:
在这种情况下添加的 FK 字段与之前使用的 M2M 字段无关,因此不会产生任何问题。
答案 6 :(得分:0)
几天来,我确实遇到了同样的错误,我尝试了在这里看到的所有内容,但仍然无法正常工作。 这对我有用:
答案 7 :(得分:0)
我遇到了同样的问题,并且发现了这篇How to Migrate a ‘through’ to a many to many relation in Django文章,确实对我解决这个问题有很大帮助。请看一看。我在这里总结他的答案,
存在三种模型,一个(CollectionProduct
)将连接多对多关系。
这是最终输出,
class Product(models.Model):
pass
class Collection(models.Model):
products = models.ManyToManyField(
Product,
blank=True,
related_name="collections",
through="CollectionProduct",
through_fields=["collection", "product"],
)
class CollectionProduct(models.Model):
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
class Meta:
db_table = "product_collection_products"
这是解决方法,
解决方案
获取您的应用标签(包装名称,例如“产品”)和M2M字段名称,并将它们与下划线结合在一起:
APPLABEL + _ + M2M TABLE NAME + _ + M2M FIELD NAME
例如,在我们的例子中就是这样:
product_collection_products
这是您的M2M直通数据库表名称。现在,您需要将M2M的贯穿模型修改为此:
还在In Django you cannot add or remove through= on M2M fields文章中找到了另一个解决方案,该解决方案将编辑迁移文件。我没有尝试过,但是看看您是否还有其他解决方案。
答案 8 :(得分:0)
这对我也有效
python manage.py migrate --fake <application name>
希望这能解决您删除数据库/迁移的问题