Django创建双向聊天室时如何捕获重复用户组合的创建错误
解决方案
第一步:修复模型层的唯一约束逻辑缺陷
你当前的unique_together只能限制(user_one, user_two)同顺序的组合不重复,如果用户B发起和用户A的聊天,两个字段顺序反过来就会生成重复房间,需要先修正这个逻辑:
# models.py 修改后 import uuid from django.db import models from rest_framework.exceptions import ValidationError class UserRoom(models.Model): room_id = models.UUIDField(default=uuid.uuid4, primary_key=True) user_one = models.ForeignKey('user.User', models.CASCADE, related_name='rooms_one') user_two = models.ForeignKey('user.User', models.CASCADE, related_name='rooms_two') class Meta: constraints = [ # 强制两个用户的组合唯一 models.UniqueConstraint(fields=['user_one', 'user_two'], name='unique_user_pair'), # 禁止用户和自己创建房间 models.CheckConstraint(check=~models.Q(user_one=models.F('user_two')), name='no_self_chat') ] def clean(self): # 保存前统一调整顺序,保证user_one的ID始终小于user_two的ID,避免顺序导致的重复判定问题 if self.user_one.id > self.user_two.id: self.user_one, self.user_two = self.user_two, self.user_one super().clean() def save(self, *args, **kwargs): self.full_clean() super().save(*args, **kwargs) def __str__(self): return f'{self.user_one} | {self.user_two} - {self.room_id}'
第二步:修改序列化器逻辑,捕获重复创建异常
直接调用create方法会触发数据库原生报错,需要提前校验同时抛出符合DRF规范的业务异常:
# serializer.py 修改后 from django.db import IntegrityError def create(self, validated_data): user_one = self.context.get('request').user user_two = validated_data['user_two'] # 调整查询顺序和模型保存逻辑对齐 if user_one.id > user_two.id: query_user_one, query_user_two = user_two, user_one else: query_user_one, query_user_two = user_one, user_two # 先查询是否存在已有的房间 if UserRoom.objects.filter(user_one=query_user_one, user_two=query_user_two).exists(): raise ValidationError('该聊天室已存在,请勿重复创建') try: room = UserRoom.objects.create(user_one=user_one, user_two=user_two) ChatMessage.objects.create( chat_room=room, sender=user_one, text=validated_data['message'] ) except IntegrityError: # 兜底捕获并发场景下的重复创建错误 raise ValidationError('该聊天室已存在,请勿重复创建') return room
你的视图层逻辑不需要额外修改,DRF会自动将序列化器抛出的ValidationError转为状态码400的响应返回给前端。
内容的提问来源于stack exchange,提问作者aman2r
相关产品推荐
相关产品推荐

