from adrf.serializers import ( ModelSerializer, CharField, SerializerMethodField, ) from django.contrib.auth import get_user_model from django.core.exceptions import SynchronousOnlyOperation from .models import Message, SystemMessage, SystemMessageRead User = get_user_model() async def _load_sender(obj): """优先命中 select_related 预加载缓存;未预加载时异步回源,避免外键懒加载""" try: return obj.sender except SynchronousOnlyOperation: if not obj.sender_id: return None return await User.objects.aget(pk=obj.sender_id) class MessageListSerializer(ModelSerializer): sender_name = SerializerMethodField() sender_avatar = SerializerMethodField() time = SerializerMethodField() is_comment = SerializerMethodField() comment_id = SerializerMethodField() article_id = SerializerMethodField() type = CharField(source='msg_type', read_only=True) extra = CharField(source='extra_info', read_only=True) link = CharField(source='target_link', read_only=True) class Meta: model = Message fields = [ 'id', 'type', 'title', 'content', 'time', 'is_read', 'sender_name', 'sender_avatar', 'extra', 'link', 'is_comment', 'comment_id', 'article_id', ] async def get_sender_name(self, obj): sender = await _load_sender(obj) if sender: return sender.nickname or sender.username return '系统' async def get_sender_avatar(self, obj): sender = await _load_sender(obj) if sender and sender.avatar: request = self.context.get('request') if request: return request.build_absolute_uri(sender.avatar.url) return sender.avatar.url return '' async def get_time(self, obj): return obj.created_at.strftime('%Y-%m-%d %H:%M') async def get_is_comment(self, obj): return obj.target_type == 'comment' async def get_comment_id(self, obj): if obj.target_type == 'comment' and obj.target_id: return str(obj.target_id) return '' async def get_article_id(self, obj): if obj.target_link: import re match = re.search(r'/article/(\d+)', obj.target_link) if match: return match.group(1) if obj.extra_info: import re match = re.search(r'/article/(\d+)', obj.extra_info) if match: return match.group(1) return None class SystemMessageSerializer(ModelSerializer): is_read = SerializerMethodField() class Meta: model = SystemMessage fields = ['id', 'title', 'content', 'category', 'icon_name', 'icon_color', 'created_at', 'is_read'] async def get_is_read(self, obj): read_ids = self.context.get('read_ids', set()) return obj.id in read_ids class SystemMessageDetailSerializer(ModelSerializer): is_read = SerializerMethodField() class Meta: model = SystemMessage fields = ['id', 'title', 'content', 'detail', 'category', 'icon_name', 'icon_color', 'created_at', 'is_read'] async def get_is_read(self, obj): request = self.context.get('request') if request and request.user.is_authenticated: return await SystemMessageRead.objects.filter( user=request.user, system_message=obj ).aexists() return False