You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 16:12:02