Django Model 数据更新的多种实现方式与注意事项
本文详细介绍Django中Model数据更新的多种方法。涵盖常规字段批量与单条更新、auto_now字段的特殊处理、JSON字典数据的高效写入,以及ForeignKey和ManyToManyField字段的更新技巧与常见报错排查。
Django Model 数据更新的常规用法
Django Model 数据更新的常规用法
假设我们的数据库表结构如下定义:
class User(models.Model):
username = models.CharField(max_length=255, unique=True, verbose_name='用户名')
is_active = models.BooleanField(default=False, verbose_name='激活状态')
若需修改用户名及激活状态,可采用以下两种主要方式:
第一种方法:
User.objects.filter(id=1).update(username='nick',is_active=True)
第二种方法:
_t = User.objects.get(id=1)
_t.username='nick'
_t.is_active=True
_t.save()
方法一适用于批量更新数据,其逻辑类似于 SQL 语句中的 update user set username='nick' where id = 1。
方法二适用于单条数据的更新,且仅能处理一条记录。在仅需更新单条数据时,推荐采用此方式。此外,该方法还具备其他优势,后续内容将详细展开。
带有 auto_now 属性字段的更新机制
带有 auto_now 属性字段的更新机制
在实际开发中,我们通常会在模型表中添加三个默认字段:
-
自增 ID:Django 默认已包含此字段。如上述建表语句所示,即使仅定义 username 和 is_active 两个字段,生成的表中也会自动包含一个自增 ID 字段。
-
创建时间:用于标识记录的创建时刻,具备 auto_now_add 属性。在创建新记录时,系统会自动填充当前时间至该字段。
-
修改时间:用于标识记录最后一次被修改的时间,具备 auto_now 属性。当记录发生任何变化时,系统会自动将当前时间填充至该字段。
具备 auto_now 字段的表结构示例如下:
class User(models.Model):
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
username = models.CharField(max_length=255, unique=True, verbose_name='用户名')
is_active = models.BooleanField(default=False, verbose_name='激活状态')
若表中包含具有 auto_now 属性的字段,且期望其能自动更新,则必须使用方法二进行更新。否则,auto_now 字段将不会触发更新,具体表现为:
_t = User.objects.get(id=1)
_t.username='nick'
_t.is_active=True
_t.save()
JSON 或字典类型数据的字段更新
JSON 或字典类型数据的字段更新
当前主流的 Web 开发模式强调前后端分离,交互数据格式普遍采用 JSON。那么,如何以最少代码便捷地将 JSON 格式数据更新至数据库?同样可使用以下两种方法:
第一种方法:
data = {'username':'nick','is_active':'0'}
User.objects.filter(id=1).update(**data)
- 值得注意的是,此方法无法自动更新具有 auto_now 属性字段的值。
- 通常在变量前添加一个星号 (*) 表示该变量为元组或列表,添加两个星号 (**) 表示该参数为字典。
第二种方法:
data = {'username':'nick','is_active':'0'}
_t = User.objects.get(id=1)
_t.__dict__.update(**data)
_t.save()
与方法一相同,此方法也无法自动更新 auto_now 字段的值。
此处用到了 dict 的一个特定方法。
第三种方法:
_t = User.objects.get(id=1)
_t.role=Role.objects.get(id=3)
_t.save()
ForeignKey 外键字段的更新
ForeignKey 外键字段的更新
若模型表中包含 ForeignKey 外键字段,应如何进行更新?
class User(models.Model):
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
username = models.CharField(max_length=255, unique=True, verbose_name='用户名')
is_active = models.BooleanField(default=False, verbose_name='激活状态')
role = models.ForeignKey(Role, on_delete=models.CASCADE, null=True, verbose_name='角色')
第一种方法:
User.objects.filter(id=1).update(role=2)
- 最简单的方式是直接将 role 字段设置为对应的 ID 值。
- 当然,也可以使用字典作为参数进行更新:
User.objects.filter(id=1).update(**{'username':'nick','role':3})
第二种方法:
_role = Role.objects.get(id=2)
User.objects.filter(id=1).update(role=_role)
- 也可以将实例对象赋值给 role 字段。
- 同样,可以使用字典作为参数进行更新:
_role = Role.objects.get(id=1)
User.objects.filter(id=1).update(**{'username':'nick','role':_role})
第三种方法:
_t = User.objects.get(id=1)
_t.role=Role.objects.get(id=3)
_t.save()
- 注意:此处 role 必须赋值为对象实例,不能直接写入 ID,否则将报错 "User.role" must be a "Role" instance。
- 当使用字典作为参数进行更新时,存在一点差异,代码如下:
_t = User.objects.get(id=1)
_t.__dict__.update(**{'username':'nick','role_id':2})
_t.save()
- ForeignKey 外键字段在字典中必须加上 `_id` 后缀,例如:{'role_id': 3}。
- role_id 后必须跟随一个 ID 值(int 或 str 类型均可),而不能直接跟随 role 实例。
ManyToManyField 字段的更新
ManyToManyField 字段的更新
若模型表中包含 ManyToManyField 字段,更新操作又有何不同?
class User(models.Model):
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
username = models.CharField(max_length=255, unique=True, verbose_name='用户名')
is_active = models.BooleanField(default=False, verbose_name='激活状态')
role = models.ForeignKey(Role, on_delete=models.CASCADE, null=True, verbose_name='角色')
groups = models.ManyToManyField(Group, null=True, verbose_name='组')
多对多(m2m)字段没有直接的更新方法,只能通过先清空再添加的方式来实现更新。
_t = User.objects.get(id=1)
_t.groups.clear()
_t.groups.add(*[1,3,5])
_t.save()
add():用于向 m2m 字段添加一个值。当需要添加多个值时,可使用列表,参考上述示例。
_t.groups.add(2) _t.groups.add(Group.objects.get(id=2))
remove():用于从 m2m 字段移除一个值。当需要移除多个值时,可使用列表,参考上述示例。
_t.groups.remove(2) _t.groups.remove(Group.objects.get(id=2))
clear():用于清空 m2m 字段的所有值。
以上关于 Django Model update 多种用法的介绍即为全部内容,希望能为大家提供参考,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









