Files
chunyu_project/chat/serializers.py
T
2026-08-05 23:59:15 +08:00

113 lines
4.2 KiB
Python

from rest_framework import serializers
from .models import FriendRequest, Friendship, Conversation, ConversationParticipant, ChatMessage
from django.conf import settings
class UserBriefSerializer(serializers.Serializer):
id = serializers.IntegerField()
username = serializers.CharField()
nickname = serializers.SerializerMethodField()
avatar = serializers.SerializerMethodField()
def get_nickname(self, obj):
return getattr(obj, 'nickname', '') or obj.username
def get_avatar(self, obj):
avatar = getattr(obj, 'avatar', None)
if avatar and hasattr(avatar, 'url'):
request = self.context.get('request')
if request:
return request.build_absolute_uri(avatar.url)
return avatar.url
return ''
class FriendRequestSerializer(serializers.ModelSerializer):
from_user = UserBriefSerializer(read_only=True)
to_user = UserBriefSerializer(read_only=True)
from_user_id = serializers.IntegerField(write_only=True, required=False)
to_user_id = serializers.IntegerField(write_only=True, required=False)
class Meta:
model = FriendRequest
fields = ['id', 'from_user', 'to_user', 'from_user_id', 'to_user_id', 'status', 'message', 'created_at', 'updated_at']
class FriendshipSerializer(serializers.ModelSerializer):
friend = serializers.SerializerMethodField()
class Meta:
model = Friendship
fields = ['id', 'friend', 'created_at']
def get_friend(self, obj):
request = self.context.get('request')
if not request:
return None
friend_user = obj.user2 if obj.user1 == request.user else obj.user1
return UserBriefSerializer(friend_user, context=self.context).data
class ConversationSerializer(serializers.ModelSerializer):
other_user = serializers.SerializerMethodField()
last_message = serializers.SerializerMethodField()
unread_count = serializers.SerializerMethodField()
class Meta:
model = Conversation
fields = ['id', 'type', 'other_user', 'last_message', 'unread_count', 'created_at']
def get_other_user(self, obj):
request = self.context.get('request')
if not request:
return None
participant = obj.participants.exclude(user=request.user).first()
if participant:
return UserBriefSerializer(participant.user, context=self.context).data
return None
def get_last_message(self, obj):
last_msg = obj.messages.order_by('-created_at').first()
if last_msg:
return ChatMessageSerializer(last_msg, context=self.context).data
return None
def get_unread_count(self, obj):
request = self.context.get('request')
if not request:
return 0
try:
participant = ConversationParticipant.objects.get(conversation=obj, user=request.user)
if participant.last_read_at:
return obj.messages.filter(created_at__gt=participant.last_read_at).exclude(sender=request.user).count()
return obj.messages.exclude(sender=request.user).count()
except ConversationParticipant.DoesNotExist:
return 0
class ChatMessageSerializer(serializers.ModelSerializer):
sender_info = UserBriefSerializer(source='sender', read_only=True)
is_own = serializers.SerializerMethodField()
reply_to_message = serializers.SerializerMethodField()
class Meta:
model = ChatMessage
fields = ['id', 'conversation', 'sender', 'sender_info', 'content', 'msg_type', 'file_url', 'reply_to', 'reply_to_message', 'is_recalled', 'is_own', 'created_at']
read_only_fields = ['sender', 'conversation']
def get_is_own(self, obj):
request = self.context.get('request')
if request and hasattr(request, 'user'):
return obj.sender == request.user
return False
def get_reply_to_message(self, obj):
if obj.reply_to and not obj.reply_to.is_recalled:
return {
'id': obj.reply_to.id,
'content': obj.reply_to.content[:50],
'sender_name': getattr(obj.reply_to.sender, 'nickname', '') or obj.reply_to.sender.username,
'msg_type': obj.reply_to.msg_type,
}
return None