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",)