Django中如何重写save()方法

前言:

在Django的开发过程中,有时会需要我们重写save()方法来实现某些应用场景,下面来聊一聊如何重写save()方法以及一些注意事项

在model中重写

先抛出一个应用的场景:

  • 我们的模型用于存储文章,里面有文章标题,内容,创建时间,修改时间
  • 需要在每次保存时更新修改时间

定义如下:

python 复制代码
class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    created_time = models.DateTimeField(auto_now_add=True)
    updated_time = models.DateTimeField(null=True)

创建时间会在生成时自动生成,更新时间由我们编写逻辑,且允许为空


使用模板:

python 复制代码
def save(self,*args,**kwargs):
    # 编写保存前的逻辑
    super().save(*args,**kwargs)
    # 编写保存后的逻辑

super().save(*args,**kwargs)是父类的保存逻辑

我们是在父类的保存逻辑基础上添加逻辑

不能舍弃父类的保存逻辑


现在的需求:由于修改时间是每一次保存的时候都需要更新,抓住关键词,保存[save()方法]。就可以翻译为每一次调用save()方法时都需要更新修改时间字段


需求明确了,那只需要在每次保存之前都把修改时间设置为当前时间即可

实现:

python 复制代码
def save(self,*args,**kwargs):
    self.updated_time = timezone.now()
    super().save(*args,**kwargs)

测试:

python 复制代码
article = models.Article(title='django中的save方法',content='这是内容')
article.save()

更新:

python 复制代码
article = models.Article.objects.get(title='django中的save方法')
article.content = '这是修改的内容'
article.save()

注意:如果此处你使用.filter.update()更新数据,此时不会调用save()方法

为了演示此处用.get().字段名重新赋值调用save()方法演示

可以看见修改时间处已经更新

在ModelForm中重写

还是先抛出一个应用的场景:

  • 我们需要把不合规的昵称换为"系统昵称"
  • 需要在保存是检查昵称并进行操作

模版语法:

python 复制代码
def save(self, commit=True):
    instance = super().save(commit=False)
    # ---- 此处编写保存逻辑
		
   	# ----
    if commit:
        instance.save()
    return instance

补充讲解:

注意如果同时调用
instance.username


self.cleaned_data['username']

此时两个的值是一样的,因为在
instance = super().save(commit=False)

时,就是利用了cleaned_data创建的instance实例对象

因为保存的时候是instance.save(),所以保存到数据库的时候

是以instance的数据

结合我之前的一篇文章可以得出总结

Django表单数据处理cleaned_data['*']和instance.*获取/修改数据的区别

save方法中会利用cleaned_data创建实例对象

在创建实例对象之前:

修改cleaned_data数据会影响到数据库

创建实例对象后:

修改instance对象才会影响到数据库

所以在创建好instance对象后修改cleaned_data不会影响到数据库

因为保存到数据库中的是利用cleaned_data创建的实例对象,在创建好实例对象后再修改已经没用了


回到正题,此时

为代码添加如下操作

python 复制代码
def save(self, commit=True):
    instance = super().save(commit=False)
    if instance.username == '不合规的昵称':
        instance.username = '系统昵称'
    if commit:
        instance.save()
    return instance

即可:

相关推荐
HackTwoHub3 小时前
AI大模型网关存在SQL注入、附 POC 复现、影响版本LiteLLM 1.81.16~1.83.7(CVE-2026-42208)
数据库·人工智能·sql·网络安全·系统安全·网络攻击模型·安全架构
l1t3 小时前
DeepSeek总结的DuckLake构建基于 SQL 原生表格式的下一代数据湖仓
数据库·sql
KmSH8umpK3 小时前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案进阶第八篇
数据库·redis·分布式
TDengine (老段)3 小时前
从施工监测到运营预警,桥科院用 TDengine 提升桥梁数据管理能力
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
S1998_1997111609•X4 小时前
论mysql国盾shell-sfa犯罪行为集团下的分项工程及反向注入原理尐深度纳米算法下的鐌檵鄐鉎行为
网络·数据库·网络协议·百度·开闭原则
KmSH8umpK5 小时前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案进阶第七篇
数据库·redis·分布式
BU摆烂会噶6 小时前
【LangGraph】持久化实现的三大能力——时间旅行
数据库·人工智能·python·postgresql·langchain
l1t7 小时前
DeepSeek总结的DuckLake 入门
数据库
Joseph Cooper7 小时前
RAG 与 AI Agent:智能体真的需要检索增强生成吗?
数据库·人工智能·ai·agent·rag·上下文工程
light blue bird7 小时前
主子端台二分法任务汇总组件
前端·数据库·.net·桌面端winform