Production is ArvanCloud -> nginx -> gunicorn, but NUM_PROXIES was 1, so DRF took ArvanCloud's edge IP as the client: every guest and every OTP request behind one edge shared a single throttle bucket (20 guest sessions an hour for everyone). Default is now 2, and /api/health reports clientIp so the proxy count can be checked from outside. PATCH /api/notifications/read-all replaces the frontend's one-PATCH-per-item loop, which spent the shared "read" budget 75 requests at a time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
32 lines
1.2 KiB
Python
32 lines
1.2 KiB
Python
from rest_framework import serializers
|
|
|
|
from .models import Notification
|
|
|
|
|
|
class NotificationItemSerializer(serializers.ModelSerializer):
|
|
id = serializers.IntegerField()
|
|
isRead = serializers.BooleanField(source='is_read')
|
|
# body و createdAt از ابتدا روی مدل بودند ولی در پاسخ نبودند، یعنی فرانت
|
|
# نه متنِ اعلان را داشت نه زمانش — و هر لیستِ اعلانی به هر دو نیاز دارد.
|
|
# هر دو فقط «اضافه» میشوند؛ هیچ فیلدی حذف یا تغییرِ نام نداده، پس
|
|
# کلاینتِ فعلی نمیشکند.
|
|
createdAt = serializers.DateTimeField(source='created_at', read_only=True)
|
|
|
|
class Meta:
|
|
model = Notification
|
|
fields = ['id', 'type', 'title', 'body', 'isRead', 'createdAt']
|
|
|
|
|
|
class NotificationListResponseSerializer(serializers.Serializer):
|
|
items = NotificationItemSerializer(many=True)
|
|
unreadCount = serializers.IntegerField()
|
|
|
|
|
|
class MarkReadResponseSerializer(serializers.Serializer):
|
|
success = serializers.BooleanField()
|
|
|
|
|
|
class MarkAllReadResponseSerializer(serializers.Serializer):
|
|
success = serializers.BooleanField()
|
|
updated = serializers.IntegerField()
|