如何伪造迁移以便不创建特定的现有中间表

时间:2015-02-24 10:46:01

标签: django django-1.7 django-migrations

我有以下模特

class VucutBolgesi(models.Model):
    site = models.ForeignKey(Site)
    bolge = models.CharField(verbose_name="Bölge", max_length=75)
    hareketler = models.ManyToManyField("Hareket", verbose_name="Hareketler", null=True, blank=True, help_text="Bölgeyi çalıştıran hareketler")


class Hareket(models.Model):
    site = models.ForeignKey(Site)
    hareket = models.CharField(verbose_name="Hareket", max_length=75 )
    bolgeler = models.ManyToManyField(VucutBolgesi, verbose_name="Çalıştırdığı Bölgeler", null=True, blank=True,
                                      help_text="Hareketin çalıştırdığı bölgeler")

我在两个表上都有相同的M2M,因为我希望在两个管理表单上显示相同的中间表。他们还必须使用相同的表(不创建两个单独的表),因为一个管理表单中的一个更改必须反映到另一个。例如,如果我通过HareketVucutBolgesi添加新的HareketAdmin,那么VucutBolgesiAdmin上也会显示相同的结果。

为实现此目的,我首先从hareketler中移除VucutBolgesi M2M字段,以便Hareketler模型创建中间表。我将其迁移,然后将hareketler添加到具有VucutBolgesi属性的db_table,以便它识别相同的中间表。

该领域的最终外观如下:

hareketler = models.ManyToManyField("Hareket", verbose_name="Hareketler", db_table="antrenman_hareket_bolgeler",
                                    null=True, blank=True, help_text="Bölgeyi çalıştıran hareketler")

当我尝试迁移时,django抛出异常

django.db.utils.OperationalError: table "antrenman_hareket_bolgeler" already exists

我应该如何伪造此迁移?

以下是我每次运行makemigrations

时创建的迁移django
dependencies = [
    ('antrenman', '0005_vucutbolgesi_hareketler'),
]

operations = [
    migrations.AddField(
        model_name='vucutbolgesi',
        name='hareketler',
        field=models.ManyToManyField(to='antrenman.Hareket', db_table=b'antrenman_hareket_bolgeler', blank=True, help_text=b'B\xc3\xb6lgeyi \xc3\xa7al\xc4\xb1\xc5\x9ft\xc4\xb1ran hareketler', null=True, verbose_name=b'Hareketler'),
        preserve_default=True,
    ),
]

注意:编辑相关的迁移文件并删除migrations.AddField不起作用,因为django会为每个migrations.AddField创建相同的makemigrations

2 个答案:

答案 0 :(得分:11)

是否可以使迁移始终被伪造,只需覆盖apply和unapply方法即可。对此的后果没有得到充分的研究,但这对我来说很有用。

在以下示例中,我们创建了一个重用django.contrib.auth.User.group的M2M表b'profile_user_groups的迁移:

from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('profile', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='user',
            name='organizations',
            field=models.ManyToManyField(db_column=b'group_id', db_table=b'profile_user_groups', related_name='members', to='profile.Organization'),
        ),
    ]

    def apply(self, project_state, schema_editor, collect_sql=False):
        return project_state.clone()

    def unapply(self, project_state, schema_editor, collect_sql=False):
        return project_state.clone()

答案 1 :(得分:3)

解决方案非常简单。

您必须确保相关迁移是唯一需要伪造的迁移操作。您必须先使用

创建迁移
python manage.py makemigrations antrenman

然后将该迁移应用于--fake

python manage.py migrate --fake antrenman

让分,其他开发者应该知道他们必须虚假相关的迁移。如果还有其他人与此人一起迁移,他们应该首先进行迁移,然后伪造这个。

太糟糕了,没有参数可以说明相关的迁移应该是真实的还是假的。