django|django 自定义.save()方法

django中,我们有时候需要自己控制数据库的存储。这就需要我们重写模型的.save()方法。
【django|django 自定义.save()方法】一般来说,我们可以这样写:

class Student(models.Model): username = models.CharField('学生姓名', max_length=16) age = models.IntegerField('年龄')def save(self, *args, **kwargs): do_something() super().save(*args, **kwargs)# 执行真正的 .save() 方法. do_something_else()

一、举个例子,使用do_something_else()的场景: 我们创建订单,订单有一个编号the_id是根据创建日期和主键pk生成的。
class Order(models.Model):def _create_the_id(self): """生成订单编号""" return self.created.date().strftime('%Y%m%d') + '_' + str(self.id)created = models.DateTimeField('创建时间', auto_now_add=True) the_id = models.CharField('订单编号', max_length=32, unique=True, null=True) title = models.CharField('订单名称', max_length=32, default='') total = models.FloatField('订单金额', default=0.0)

在这里,我们的the_id属性依赖于id,所以我们必须先执行.save()然后再进行更新。
>>> order = Order(title='订单的标题****', total=25.5) >>> order.save()# 保存进数据库,获取 id>>> order.the_id = order._create_the_id() >>> order.save() # 更新 the_id 属性

这里就有一个问题,我们需要在每个.save()执行后都执行
>>> order.the_id = order._create_the_id()

更好的方法是重写.save()方法
def save(self, force_insert=False, force_update=False, using=None, update_fields=None): # 执行 save(), 将数据保存进数据库 super().save( force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields ) self.the_id = self._create_the_id()# 再次执行 save(), 将数据更新到数据库 # 注意这里的参数,必须设置 force_update=True,否则会创建新的数据 super().save( force_insert=False, force_update=True, using=using, update_fields=['the_id'] )

当我们重写.save()后,就不用考虑会不会忘记执行更新the_id操作了。现在直接执行.save()就会自动帮我们更新the_id
二、在.save()之前执行do_something() 在数据库中,有些属性属于派生属性,也就是说它们是依据其它属性生成的。
class Order(models.Model): created = models.DateTimeField('创建时间', auto_now_add=True) title = models.CharField('订单名称', max_length=32, default='') num = models.IntegerField('商品数量') price = models.FloatField('商品价格') total = models.FloatField('订单金额', default=0.0)

在上述订单模型中,total应该是在后端存储时自动计算,而不是接收前端传给我们的数据。
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):self.total = self.num * self.price# 执行 save(), 将数据保存进数据库 super().save( force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields )

    推荐阅读