首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >django模型pre_save update()存在问题

django模型pre_save update()存在问题
EN

Stack Overflow用户
提问于 2022-06-11 09:04:30
回答 1查看 113关注 0票数 0

背景:

我有具有属性is_obsolete (默认设置为False)的标记模型。

代码语言:javascript
运行
复制
class Tag(model.Model):
    ...
    is_obsolete = False

我有StatusInfo模型,它有一个外键可以通过"affected_tag“标记。

代码语言:javascript
运行
复制
class StatusInfo(models.Model):
    ...
    affected_tag = ForeignKey(Tag)

当创建StatusInfo实例时,它们会触发pre_save()信号以更改<StatusInfo>.affected_tag.is_obsolete=True

代码语言:javascript
运行
复制
@receiver(pre_save, sender=StatusInfo)
def status_change_modification(sender, instance, *args, **kwargs):
    """
        Changes tags and concepts to be obsolete or deprecated.
        if a tag is obsolete or deprecated, all of the tag's concepts are obsolete or deprecated
        
    """

    assert hasattr(instance.affected_tag, "id")

    # set up variables
    kwargs = {}
    if instance.status == "d":
        kwargs["is_deprecated"] = True
    elif instance.status == "o":
        kwargs["is_obsolete"] = True

    inner_tag_status_change(instance, **kwargs)



def inner_tag_status_change(instance, **kwargs):
    """
    update the is_updated fields for status_info
    kwargs is either:
    kwargs = {'is_obsolete': True} # or {'is_deprecated': True}
    """
    affected = Tag.objects.filter(id=instance.affected_tag.id).first()
    affected.__dict__.update(**kwargs)
    affected.save(update_fields=list(kwargs.keys()))

问题

我不明白的是,为什么当它到达测试的底部时,我仍然有标记实例self.soon_to_be_obsolete_tag.is_obsolete == False

我尝试过.update(**kwargs).save(updated_fields=list(kwargs.keys()))在inner_tag_status_change()中,但是它没有保存更改--在调试模式中执行它时,它看起来很好--然后返回到测试的最后一行。我是在处理一个单独的副本,还是在缓存我应该检查的东西?

在测试/测试状态模型. in中

代码语言:javascript
运行
复制
    def test_status_set_tag_info_obsolete(self):
        """ check to see if the creation of a statusInfo 
            object which runs a pre_save signal changes 
            the soon_to_be_obsolete_tag to is_obsolete=True
        """
    
        self.assertFalse(self.soon_to_be_obsolete_tag.is_obsolete)
        self.main_status_info = StatusInfoFactory(
            affected_tag=self.soon_to_be_obsolete_tag,
            status="o",  # obsolete
            by=self.new_replacement_tag,
        )
    
        self.assertTrue(self.soon_to_be_obsolete_tag.is_obsolete)  # still False
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-13 20:31:12

根据您的测试和预保存逻辑,看起来您正在更新数据库中的标记,但是Django对附加到模型的标记对象的缓存没有更新。

因此,我认为问题在于,在status_change_modificationinner_tag_status_change中,您都访问了instance.affected_tag,但没有直接更新instance.affected_tag。相反,您使用一个额外的查询从数据库中抓取该标记,然后保存它。

我猜如果你把你的测试更新到这个,它就会起作用:

代码语言:javascript
运行
复制
self.assertTrue(Tag.objects.get(id=self.soon_to_be_obsolete_tag).is_obsolete)

或者,如果您使用refresh_from_db强制对self.soon_to_be_obsolete_tag进行刷新,那么这也应该是有效的:

代码语言:javascript
运行
复制
self.soon_to_be_obsolete_tag.refresh_from_db()
self.assertTrue(self.soon_to_be_obsolete_tag.is_obsolete)

您还可以考虑更新您的inner_tag_status_change逻辑,以直接更新标记(我不确定这是否会解决您正在经历的问题,但它将删除可能不需要的额外SELECT查询):

代码语言:javascript
运行
复制
def inner_tag_status_change(instance, **kwargs):
    instance.affected_tag.__dict__.update(**kwargs)
    instance.affected_tag.save(update_fields=list(kwargs.keys()))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72583034

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档