【问题标题】:Django/South: save() not working as expected when adding a foreign key to a new tableDjango/South:将外键添加到新表时,save() 无法正常工作
【发布时间】:2013-11-19 02:04:13
【问题描述】:

我刚开始研究South框架,等待Django 1.7版本发布和生产就绪。

我处于这种起始状态:

class TableA(models.Model):
    CustomEntityA_ctype = models.ForeignKey(ContentType, related_name="tableB_related_name")    
    CustomEntityA_oid   = models.PositiveIntegerField()
    CustomEntityA       = generic.GenericForeignKey('CustomEntityA_ctype',
                                                    'CustomEntityA_oid')

我希望将这些方案迁移到类似的东西中

class TableB(models.Model):
    CustomEntityB_ctype = models.ForeignKey(ContentType, related_name="tableB_related_name")    
    CustomEntityB_oid   = models.PositiveIntegerField()
    CustomEntityB       = generic.GenericForeignKey('CustomEntityB_ctype',
                                                    'CustomEntityB_oid')

class TableA(models.Model):
    tableB_entity  = models.ForeignKey(TableB, 
                                       related_name='tableA_related_name',
                                       null=False)        

为了得到这个,我已经设置了一个适当的初始迁移,然后我的中间方案是这样的

class TableB(models.Model):
    CustomEntityB_ctype = models.ForeignKey(ContentType, related_name="tableB_related_name")    
    CustomEntityB_oid   = models.PositiveIntegerField()
    CustomEntityB       = generic.GenericForeignKey('CustomEntityB_ctype',
                                                    'CustomEntityB_oid')

class TableA(models.Model):
    CustomEntityA_ctype = models.ForeignKey(ContentType, related_name="tableB_related_name")    
    CustomEntityA_oid   = models.PositiveIntegerField()
    CustomEntityA       = generic.GenericForeignKey('CustomEntityA_ctype',
                                                    'CustomEntityA_oid')

    tableB_entity  = models.ForeignKey(TableB, 
                                       related_name='tableA_related_name',
                                       null=True)        

至于 South 教程,我尝试将迁移分为三个部分:

  1. 第一个 --auto 迁移到这个中间模型
  2. 生成迁移 python 脚本的数据迁移
  3. 最终的 --auto 向最终模型的迁移

这是我的转发功能的内容

def forwards(self, orm):
    "Write your forwards methods here."
    # Note: Don't use "from appname.models import ModelName". 
    # Use orm.ModelName to refer to models in this application,
    # and orm['appname.ModelName'] for models in other applications.
    for tableA_entity in orm.TableA.objects.all():
        ctype = tableA_entity.CustomEntityA_ctype
        oid   = tableA_entity.CustomEntityA_oid

        tableB_entity = orm.TableB.objects.create(CustomEntityB_ctype=ctype,
                                                  CustomEntityB_oid=oid,
                                                  )

        print "created a tableB_entity", tableB_entity
        tableA_entity.tableB_entity = tableB_entity
        tableA_entity.save()

        tableA_entity_FROMDB = orm.TableA.objects.all()[0]

        print "tableA_entity_FROMDB.tableB_entity: ", tableA_entity_FROMDB.tableB_entity

当我调用迁移步骤时,我得到一个正确创建和打印的 tableB_entity,但是当我打印最后两行的查询结果时,我得到一个空结果。总体结果是 save() 函数似乎根本不起作用。如果我进入 manage.py shell 并查询模型,我会在 TableB 中得到预期的结果,但 TableA 中对应实体的外键为空。

有人可以向我解释一下吗?

提前非常感谢!

【问题讨论】:

    标签: python django django-south data-migration


    【解决方案1】:

    到目前为止,我发现让它工作的唯一方法是将方案和数据迁移分成两组不同的迁移。

    1. 在第一个中,我将架构/数据迁移到具有这三个字段的 TableB。
    2. 在第二个中,我将外键添加到TableA,并将上一步创建的TableB实体分配给对应的TableA实体。

    显然,这不是最优的:如果在第一步中应该创建一个多对一关系的实体目标,那么在第二次迁移期间,TableA 的哪个实体应该指向新创建的项目并不简单.缓解这种情况的一种方法可能是创建一个从 TableB 到 TableA 的临时反向外键,这有助于找到要引用的原始 TableA 实体,然后在进一步的迁移中将其删除。

    在接受这个之前,我会再等一段时间,以便让其他人提出“正确”的答案:)

    【讨论】:

    • 好的,我会添加这个以供将来参考。原始帖子的“不当行为”似乎与我使用的特定后端有关,即 sqlite3。切换到 Postgres,同样的迁移脚本很有魅力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-08
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多