Полиморфные модели сериализатора - PullRequest
0 голосов
/ 22 февраля 2019

Я использую Полиморфную модель для настройки уведомлений:

Мои модели:

class Notification(PolymorphicModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created_by = models.ForeignKey(ElsUser, on_delete=models.CASCADE, default=None, related_name="creatednotifications")
    created_on = models.DateTimeField(default=timezone.now)
    created_for = models.ForeignKey(ElsUser, on_delete=models.CASCADE, default=None, related_name="receivednotifications")
    read = models.DateTimeField(default=None, null=True, blank=True)
    message = models.CharField(default=None, blank=True, null=True, max_length=800)

    @property
    def total(self):
        return self.objects.filter(created_for=self.request.user).count()

    @property
    def unread(self):
        return self.objects.filter(created_for=self.request.user,read=None).count()

    @property
    def read(self):
        return self.objects.filter(created_for=self.request.user).exclude(read=None).count()    

class WorkflowNotification(Notification):
    # permission_transition = models.ForeignKey(WorkflowStatePermissionTransition, on_delete=models.CASCADE)
    action = models.ForeignKey(UserAction, on_delete=models.CASCADE)

В настоящее время у меня есть только одна модель WorkFlowNotification, унаследованная от Полиморфноймодель, но многие будут там в будущем.

Я пытаюсь получить количество (общее количество) уведомлений для вошедшего в систему пользователя в API. Итог задается как поле свойства, чтобы помочь в том же

мой сериализатор:

class NotificationSerializer(serializers.ModelSerializer):
    total = serializers.ReadOnlyField()
    read = serializers.ReadOnlyField()
    unread = serializers.ReadOnlyField()

    class Meta:
        model = Notification
        fields = ['id', 'total','read', 'unread']

В представлении:

   class NotificationsMeta(generics.ListAPIView):
    serializer_class = NotificationSerializer
    queryset = Notification.objects.all()

Когда я пытаюсь запустить сервер, он показывает:

  Got AttributeError when attempting to get a value for field `total` on serializer `NotificationSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `WorkflowNotification` instance.
Original exception text was: Manager isn't accessible via WorkflowNotification instances.

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Поскольку вам нужны только «метаданные», какой смысл в создании сериализатора модели?Или любой сериализатор, в этом отношении?Сериализаторы предоставят вам сериализованные экземпляры объектов вашей модели.Поэтому, если у вас есть несколько объектов, вы получите в ответ несколько сериализованных объектов.

Просто сделайте ваш взгляд нормальным APIView .Поскольку нет необходимости сериализации чего-либо.

class NotificationsMeta(APIView):
    def get(self, request, format=None):
        qs = Notification.objects.filter(created_for=self.request.user)
        response = {
            'total': qs.count(),
            'read': qs.filter(read=None).count(),
            'unread': qs.exclude(read=None).count()
        }
        return Response(response)

Теперь удалите эти функции свойств из вашей модели.

Я не проверял ваши запросы, просто скопировал их из вашей модели.Вам нужно будет проверить, правильно ли они работают.Надеюсь, это поможет.

0 голосов
/ 22 февраля 2019

Я не уверен, что вызов свойства модели, отвечающего за запросы в модели, может дать соответствующие данные из сериализатора.К сожалению, у меня есть пробел в знаниях об этом.Я думаю об альтернативном решении.Я надеюсь, что следующее должно работать.

class NotificationSerializer(serializers.ModelSerializer):
    total = serializers.serializers.SerializerMethodField()

    read = serializers.ReadOnlyField()
    unread = serializers.ReadOnlyField()

    class Meta:
        model = Notification
        fields = ['read', 'unread']


    def get_total(self, obj):
        user =  self.context['request'].user 
        return Notification.objects.filter(created_for=user).count()

Если это сработает, то вы сможете делать подобные вещи как для чтения, так и для непрочитанных.

Чтобы получить уведомление для current_user, нам нужно перезаписать get_queryset из представления.

   class NotificationsMeta(generics.ListAPIView):
    serializer_class = NotificationSerializer
    def get_queryset(self):
       return Notification.objects.filter(created_for=self.request.user)
...