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

标签 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()

这很好用,但是我需要更改系统以允许某些具有外键的模型,因为当实例被存档/删除时,相关记录也会随之删除。所以我解决这个问题的想法是将草稿记录的更改复制到以前的记录,然后删除草稿,从而保留外键相关记录。

解决思路

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()

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

如有任何帮助,我们将不胜感激,如果我找错了树,请告诉我。

最佳答案

在大量浏览和阅读 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()

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

我进行了几次测试,这似乎以最少的代码和无需额外安装的方式实现了我一直在寻找的东西。

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

关于python - 在 Django 中将字段从一个实例复制到另一个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26975000/

相关文章:

python - 即使引发 ValueError,Pytest assertRaisesWithMessage(ValueError) 也会失败

python - 仅将 Python 列表中的日期时间转换为年份

python - 为什么我的 Django 项目同时显示在 subdomain 和 localhost 中?

django - XML 向亚马逊 MWS 提交得很好,但价格没有更新

python /django : model object has no attribute 'prefetch_related'

Django 在尝试保存对象属性时抛出 "invalid literal for int() with base 10: ' '"

python - 如何解决[SSL : CERTIFICATE_VERIFY_FAILED] Error when Using urllib without bypassing SSL verification

python subprocess.call() 找不到 Windows Bash.exe

python - 我如何创建mysql数据库的增量备份

django - 每次我重新启动笔记本电脑时,我都必须再次在 Pycharm 中设置 Django。错误 请为项目启用 Django 支持