【问题标题】:How to fake migrations for not to create a specific existing intermediary table如何伪造迁移以不创建特定的现有中间表
【发布时间】:2015-04-25 22:50:32
【问题描述】:

我有以下型号

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,因为我希望在两个管理表单上显示相同的中间表。他们还必须使用同一个表(而不是创建两个单独的表),因为一个管理表单中的一个更改必须反映到另一个。比如,如果我通过HareketAdminVucutBolgesi 添加一个新的Hareket,那么VucutBolgesiAdmin 上也应该可以看到相同的结果。

为了实现这一点,我首先从VucutBolgesi 中删除hareketler M2M 字段,以便Hareketler 模型将创建中间表。我将其迁移,然后将 hareketler 添加到 VucutBolgesidb_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

我应该如何伪造这个迁移?

以下是 django 每次运行时创建的迁移makemigrations

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 fo 不起作用,因为 django 为每个 makemigrations 创建了相同的 migrations.AddField

【问题讨论】:

    标签: django django-1.7 django-migrations


    【解决方案1】:

    解决方案非常简单。

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

    创建迁移
    python manage.py makemigrations antrenman
    

    然后使用 --fake 应用该迁移

    python manage.py migrate --fake antrenman
    

    障碍是,其他开发人员应该知道他们必须伪造相关迁移。如果这个迁移旁边还有其他迁移,他们应该先进行迁移,然后 fake 这个迁移。

    可惜没有参数告诉相关迁移是真的还是假的。

    【讨论】:

      【解决方案2】:

      是否有可能使迁移始终被伪造,只需覆盖 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()
      

      【讨论】:

      • 这是目前我最喜欢的关于整个 SO!一个 5 年前的帖子救了我的命!!!谢谢!!
      猜你喜欢
      • 1970-01-01
      • 2019-02-06
      • 2016-03-13
      • 2018-05-22
      • 1970-01-01
      • 2018-08-15
      • 2012-05-20
      • 1970-01-01
      • 2020-04-18
      相关资源
      最近更新 更多