Django搭配PostgreSQL时如何向模型ArrayField追加数据值
问题根因
代码存在两个致命错误,直接导致ArrayField写入、追加失败:
- Python列表的
append()是原地修改方法,执行后不会返回新列表,返回值固定为None。执行attend.time = attend.time.append(xxx)的逻辑,本质是把time字段直接赋值为None,原有数据会被直接清空。 - 通过
get_or_create生成新记录时,time字段默认值是*NULL(模型配置了null=True),直接对None调用append()会触发NoneType属性错误*,新记录根本无法正常写入。
基础修复方案
调整逻辑:新建记录时提前把time字段初始化为空列表,追加值时不要接收append()的返回值,直接修改列表后保存即可。
修正后的视图代码:
attend, created = models.AttendanceModel.objects.get_or_create( user=fingerprint.user, date=attendance_date, # 新建记录时直接初始化time为空列表,避免操作None值 defaults={'time': []} ) # 直接在原有列表上追加值,不要重新赋值append的返回结果 attend.time.append(attendance.timestamp.time()) attend.save()
并发场景优化方案
如果存在同一用户同一日期多条打卡数据并发写入的场景,上面的先查后改逻辑会出现竞态条件:读取旧列表到内存、追加值、保存的间隙如果有其他请求也修改了该字段,会导致中间写入的数据丢失。这种场景可以用Django内置的ArrayAppend函数,直接在数据库层面完成数组追加,不需要提前读取字段值:
from django.contrib.postgres.functions import ArrayAppend # 单条语句完成存在则更新、不存在则创建+追加的逻辑,避免并发冲突 obj, created = models.AttendanceModel.objects.update_or_create( user=fingerprint.user, date=attendance_date, defaults={'time': []} ) # 数据库层面执行数组追加 obj.time = ArrayAppend('time', attendance.timestamp.time()) obj.save()
注意:使用数据库层面追加方案时,必须保留
defaults里的空列表初始化配置,否则对NULL值执行数组追加操作会抛出数据库错误。
内容的提问来源于stack exchange,提问作者Nahidujjaman Hridoy
相关产品推荐
相关产品推荐

