djangodjango-rest-frameworkdjango-polymorphic

Polymorphic models serializer


I'm using a Polymorphic model for setting up notifications:

My models:

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)

Currently i have just one model WorkFlowNotification inheriting from the Polymorphic model,but many would be there in the future.

Im trying to get the count(total) of notifications for the logged in user in the API ..total is given as property field to help in the same

my serializer:

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

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

In the view:

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

When i try to run the server it shows:

  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.

Solution

  • I am not sure about how calling a model property who is responsible for querying in model can give appropriate data from serializer. Unfortunately i do have knowledge gap about that. I am thinking about an alternative solution. I hope following should work.

    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()
    

    If this work then you can able to do similar kind of thing for read and unread too.

    In order to get notification for current_user we need to overwrite get_queryset from view.

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