Django复制BlogPost模型实例失败,已处理外键关联仍测试不通过求助
现有copy方法问题梳理
- 实例保存顺序错误:新的
BlogPost实例未先执行save()生成主键,就尝试添加到作者的反向关联中,外键关联依赖实例主键,该操作必然失效 - 无效全表扫描:不需要遍历所有
Author实例匹配原作者,直接复用self.author即可,数据量大时会触发严重性能问题 - 关联操作冗余:给
Comment设置blog_post = new并保存后,外键关联已经建立,不需要额外调用new.comments.add(comment),也不需要反复保存new实例 - 多余数据库查询:
self本身就是原BlogPost实例,不需要再次通过pk查询获取原实例 - 时区适配问题:直接调用
datetime.now()没有适配Django项目的时区配置,推荐使用django.utils.timezone.now(),同时要确保对应模块已导入
修正后的代码
from django.utils import timezone from django.db import models class Author(models.Model): name = models.CharField(max_length=50) class BlogPost(models.Model): title = models.CharField(max_length=250) body = models.TextField() author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='blog_posts') date_created = models.DateTimeField(auto_now_add=True) def copy(self): # 克隆原实例字段,重置主键和创建时间 new_blog = BlogPost.objects.get(pk=self.pk) new_blog.pk = None new_blog.id = None new_blog.date_created = timezone.now() # 直接绑定原作者,不需要遍历 new_blog.author = self.author # 先保存生成主键,再处理关联数据 new_blog.save() # 复制关联评论 for comment in self.comments.all(): comment.pk = None comment.blog_post = new_blog comment.save() # 返回新实例方便调用 return new_blog class Comment(models.Model): blog_post = models.ForeignKey(BlogPost, on_delete=models.CASCADE, related_name='comments') text = models.CharField(max_length=500)
测试注意事项
测试时需要确保在调用copy()方法后,再对新实例的属性、作者关联、评论关联进行断言,避免未执行复制逻辑就做校验的问题。
内容的提问来源于stack exchange,提问作者Sarah Ghanei
相关产品推荐
相关产品推荐

