Django模型编写对象复制copy方法无法生成新实例如何解决
问题原因
- 原代码中
BlogPost.objects.get(id=self.id)获取的是当前已存在的对象实例,调用update()只会修改现有数据库记录的字段值,不会生成新的独立实例 - QuerySet的
update()方法返回值是受影响的行数(整数类型),并非模型实例,后续调用save()方法、读取id属性都会抛出类型错误 - 没有清空原实例的主键值,Django无法触发新增数据库记录的逻辑
修正后的实现
你可以通过清空实例主键的方式让Django识别为新对象,自动插入新的数据库记录,修正后的copy方法如下:
from datetime import datetime class Author(models.Model): name = models.CharField(max_length=50) class BlogPost(models.Model): title = models.CharField(max_length=250) body = models.CharField(max_length=None) author = models.ForeignKey(Author ,on_delete=models.CASCADE) # 小优化:auto_now_add 传入布尔值True即可,Django会自动在首次创建记录时填充当前时间 data_created = models.DateTimeField(auto_now_add=True) def copy(self): # 基于当前实例生成复制对象 new_post = BlogPost.objects.get(id=self.id) # 清空主键,触发新增记录逻辑 new_post.pk = None new_post.id = None # 手动更新创建时间为当前时间 new_post.data_created = datetime.now() # 保存生成全新独立实例 new_post.save() # 可选:如果需要连带复制当前博文关联的所有评论,取消注释以下代码 # for origin_comment in self.comment_set.all(): # origin_comment.pk = None # origin_comment.blog_post = new_post # origin_comment.save() return new_post.id class Comment(models.Model): blog_post = models.ForeignKey(BlogPost , on_delete=models.CASCADE) text = models.CharField(max_length=500)
额外说明
如果你的模型后续新增了其他字段,上述代码无需修改即可自动适配新字段的复制,仅需要特殊处理有唯一约束、需要单独调整值的字段即可。
内容的提问来源于stack exchange,提问作者abolfazlmalekahmadi
相关产品推荐
相关产品推荐

