在Django中将字段从一个实例复制到另一个

Kar*_*arl 5 python django

我有以下代码,它将一个现有实例复制并“归档”到另一个模型中,然后删除它,并用草稿副本替换它。

当前代码

def archive_calc(self, rev_num, primary_field):
    model_a = Calc.objects.get(tag_number__tag_number = primary_field, revision_number = rev_num) #Current Revision instance
    model_b = CalcArchive() #Draft instance

    #Copies data to archive model
    for field in model_a._meta.fields:
        setattr(model_b, field.name, getattr(model_a, field.name))

    model_b.pk = None
    model_b.current_revision = False
    model_b.save()

    model_a.delete()
Run Code Online (Sandbox Code Playgroud)

效果很好,但是我需要更改系统以允许某些带有外键的模型,因为当实例被存档/删除时,相关记录也随之删除。因此,解决此问题的想法是将草稿记录中的更改复制到先前的记录中,然后删除草稿,从而维护与外键相关的记录。

解决思路

def archive_calc(self, rev_num, primary_field):
    model_a = Calc.objects.get(tag_number__tag_number = primary_field, revision_number = rev_num) #Current Revision instance
    model_b = CalcArchive() #Archive Instance
    model_c = Calc.objects.get(pk = self.object.pk) #Draft instance

    #Copies data to archive model
    for field in model_a._meta.fields:
        setattr(model_b, field.name, getattr(model_a, field.name))

    model_b.pk = None
    model_b.current_revision = False
    model_b.save()

    #Copies data from draft instance to current revision instance
    for field in model_c._meta.fields:
        setattr(model_a, field.name, getattr(model_c, field.name))

    model_c.delete()
Run Code Online (Sandbox Code Playgroud)

不幸的是,以上解决方案无法正常工作,只是似乎忽略了该副本,并按照“当前代码”继续工作。如果我model_a.save()for field in model_c._meta.fi...系统陷入循环并最终抛出之后添加maximum recursion depth exceeded in cmp

与往常一样,任何帮助将不胜感激,如果我叫错了树,请告诉我。

Kar*_*arl 3

经过大量研究和阅读 Django 文档后,我想出了一个看起来非常不错、简单的解决方案。

def archive_calc(self, rev_num, primary_field):
    model_a = Calc.objects.get(calc_details__calc_serial_number = primary_field, revision_number = rev_num)
    model_b = CalcArchive()

    object_list_annual = model_a.calcreview_set.filter(calc__calc_details = primary_field)
    object_list_ageing = model_a.calcitem_set.filter(calc__calc_details = primary_field)

    for obj in object_list_annual:
        obj.calc_id = self.object.id
        obj.save()
    for obj in object_list_ageing:
        obj.calc_id = self.object.id
        obj.save()

    for field in model_a._meta.fields:
        setattr(model_b, field.name, getattr(model_a, field.name))
    model_b.pk = None
    model_b.current_revision = False
    model_b.save()

    model_a.delete()
Run Code Online (Sandbox Code Playgroud)

_id这通过将字段设置为与 相同来“移动”相关对象self.object.id

我已经运行了几次测试,这似乎完全达到了我所寻找的目标,只需最少的代码,无需额外安装。

希望这对某人有帮助,并请随时指出我的回答中任何潜在的陷阱。