使用cqlengine操作Cassandra时重复更新旧条目的问题排查
你遇到的这个问题,根源是UUID主键的默认值设置错误,再加上Serializer的create方法存在冗余逻辑,两者共同导致了这个奇怪的现象。
1. 核心原因:UUID默认值只生成一次
先看你的TestUserProf模型定义:
user_id = columns.UUID(primary_key=True, default=uuid.uuid4())
这里你传的是uuid.uuid4()——这是直接调用函数得到一个固定UUID值,这个值会在Django服务器启动、加载TestUserProf类的瞬间就被确定下来。之后每次调用create接口,都会复用这个固定UUID作为主键。
Cassandra是基于主键唯一识别记录的,当你第二次提交请求时,主键和之前最后一条记录完全一致,所以Cassandra会执行更新操作而非插入新记录。重启服务器后,类会重新加载,生成一个新的固定UUID,所以第一次提交又能正常创建条目,但后续提交又会重复使用这个新的固定UUID,继续更新同一条记录。
2. Serializer的create方法冗余且有误
你的TestProfSerializer的create方法里,明明已经通过objects.create创建了数据库记录并得到了obj,但最后却返回TestUserProf(**validate_data)——这不仅是多余的,还可能导致后续逻辑拿到未持久化的实例,引发其他问题。
修复步骤
第一步:修正UUID默认值的设置
把default=uuid.uuid4()改成default=uuid.uuid4——也就是传递函数本身,而非函数调用的结果。这样每次创建新实例时,cqlengine都会主动调用uuid.uuid4()生成一个全新的UUID:
class TestUserProf(Model): user_id = columns.UUID(primary_key=True, default=uuid.uuid4) # 去掉括号! emp_id = columns.Text() address = columns.UserDefinedType(address)
第二步:修正Serializer的create方法
删掉冗余的返回语句,直接返回刚创建好的obj:
def create(self, validated_data): """ Create new entry in ProfSerializer :params validated_data :return """ addr_data = validated_data.get('address') obj = TestUserProf.objects.create( emp_id=validated_data.get('emp_id'), address=address( name=addr_data.get('name'), age=addr_data.get('age'), street=addr_data.get('street'), zipcode=addr_data.get('zipcode') ) ) return obj # 返回实际持久化的对象
第三步:重启服务器测试
修改完成后重启Django服务器,多次提交请求,应该每次都会创建新的条目,不会再出现更新旧记录的情况了。
额外验证小技巧
可以在create方法里加一行打印,确认每次生成的user_id都是不同的:
print(f"Generated user_id: {obj.user_id}")
这样能直观看到UUID是否每次都在变化,验证修复效果。
内容的提问来源于stack exchange,提问作者Shihabudheen K M

