Django Rest Framework пользовательское поле с возможностью чтения, зависящее от связанной модели

предлагая models.py как:

class User(AbstractUser):
    pass

class Notification(models.Model):
    value = models.CharField(max_length=255)

class NotificationUserLink(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    notification = models.ForeignKey(Notification, on_delete=models.CASCADE)
    active = models.BooleanField(default=True)

Смысл нормализации вместо того, чтобы просто иметь поле пользователя в самом уведомлении, заключается в том, что когда я хочу отправить одно и то же уведомление сотням людей, мне нужен только 1 объект уведомления. Предположим, что у меня также есть конечная точка в views.py, как показано ниже, где пользователь может видеть все свои уведомления и только свои уведомления, что достигается путем фильтрации набора запросов.

class NotificationViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.NotificationSerializer
    model = Notification
    lookup_field='pk'
    def get_queryset(self):
        user = self.request.user
        return Notification.objects.filter(notificationuserlink__user=user)

Теперь пара "user" и "notification" в модели NotificationUserLink формирует ключ-кандидат (они уникальны вместе. В настоящее время только с помощью бизнес-логики, но в какой-то момент я добавлю фактическое ограничение в базу данных).

Поэтому, учитывая пользователя в запросе, каждое уведомление (в фильтрованном наборе запросов) будет иметь 1 и только 1 NotificationUserLink на этого пользователя. Поэтому, с точки зрения пользователя, это уведомление либо активно, либо нет, в зависимости от поля "active" в NotificationUserLink.

Я хочу добиться того, чтобы включить это поле ("active") в сериализацию уведомления. Т.е. если пользователь обращается к этой конечной точке, он должен видеть уведомления типа:

[
{
    "value": "Bob commented on your post",
    "active": False
},
{...}, ...
]
etc

Я думаю, что для достижения этого мне нужно переопределить метод "list" в представлении. Но я не знаю, как это сделать. Сериализатору передается queryset в методе list, так что я не уверен, как вводить туда данные.

В настоящее время сериализатор выглядит следующим образом:

class NotificationSerializer(serializers.ModelSerializer):
    class Meta:
        model=Notification
        fields=("value",)

Вы можете annotate статус ссылки следующим образом в вашем кверисете:

Notification.objects.filter(
    notificationuserlink__user=user
).annotate(
    active=F('notificationuserlink__active')
)

А затем вы можете добавить поле только для чтения active в ваш сериализатор:

class NotificationSerializer(serializers.ModelSerializer):
    active = serializers.BooleanField(read_only=True)
    class Meta:
        model = Notification
        fields = ("active", "value",)
Вернуться на верх