Django的get产生对象所引发的一个坑(get save后却改变了其他值)

本文探讨了一个在Django项目中遇到的bug,当使用ORM的get方法更新对象属性并调用save时,其他未修改的属性被意外更改。通过分析原因,发现对象初始化时的状态保存导致了这一问题,并提出了每次重新创建对象作为解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前文

  接手同事的一个Django项目,项目虽然没有基于drf框架来写,不过也是用了serializer和restful规范来进行开发的项目,而在近期在用django的orm里的get来操作数据库的时候就产生了bug,当get获取到对象后,改变其中的一个值,save后却导致其他值变化了。

问题描述

  这个bug是由两点来导致的,首先在接收到post请求的时候,会将参数送到一个处理类去处理,比如这个处理类是处理person的一个eat apple的行为,而在数据库里保存着一个苹果的数据表,里面有苹果的状态和苹果的颜色,代码如下:

class personEatApple:
	def __init__(self,apple_id):
		self.apple_id = apple_id #apple_id是数据库里的主键
		self.obj = Apple.objects.get(id=self.apple_id) 
	
	def eat(self):
		self.obj.status = "eat"
		obj.save()
		self.changeColor()
		self.obj.status = "finish"
		obj.save()

	def changeColor(self):
		obj = Apple.objects.get(id=self.apple_id) 
		obj.color = 'red'
		obj.save()

  可以看到通过eat方法将苹果从eat改为finish了,中间当然还执行了一些操作,而在中间我又写了另一个代码将苹果的颜色改成红色(假定原来是绿色),此时查看这张表的内容,颜色和状态分别是什么呢?答案是:颜色:绿色,状态:finish

解决

  解决这个问题要弄懂两点,第一点就是get的保存会保存所有内容,也就是即使你只改变了status状态这个字段,当你save的时候,通过官方文档我们清楚是会插入一条数据,所以除了你改变的那条数据,其他数据保持不变地插入一条数据(可能是删了原来的数据,不过这个文档里没找到),文档(https://docs.djangoproject.com/en/3.0/ref/models/instances/#django.db.models.Model.save)如下:
在这里插入图片描述
  所以从第一点我们知道了只要是save就会插入一条数据,而在插入之前Django会判断是update还是insert操作。而第二点更重要的是,我的对象是在init里创建的,所以self.obj保存的状态是在eat动作刚开始就保存着了,此时这里color是绿色,而我在中间用changeColor这个独立的方法改变了color为red,但是在self.obj里color还是绿色,此时改变status为finish并save,则color由于save的插入还是绿色。
  可以说这个bug非常隐秘,当然期间你也可以在changeColor里用self.obj来改变状态,不过这个非常不方便,比如中间要做的事非常复杂,又需要一个额外的类来处理,那此时就要继承吗?还有比如别人接手(比如我)代码,那就很容易造成bug,所以建议对象还是不要再init里创建,而是每次都重新创建比较好!

总结

  解决方法很简单,即把对象创建从init里移除,每次都重新创建即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值