Home > Back-end >  When including resources DRF returns my soft deleted records
When including resources DRF returns my soft deleted records

Time:05-03

I have DRF API that supports including the books of an author in an authors get request.

Our API has a soft delete system where Book(2) marked as deleted.

But when I do the request below Book(2) is still included in the response.

I would like to have only Book(1) in the response of this request.

GET http://localhost/authors/2?include=books

API returns to me:

{
    "data": {
        "type": "Author",
        "id": "2",
        "attributes": {...},
        "relationships": {
            "books": {
                "meta": {
                    "count": 2
                },
                "data": [
                    {
                        "type": "Book",
                        "id": "1"
                    },
                    {
                        "type": "Book",
                        "id": "2"
                    }
                ]
            }
        }
    },
    "included": [
        {
            "type": "Book",
            "id": "1",
            "attributes": {...}
        },
        {
            "type": "Book",
            "id": "2",
            "attributes": {...}
        }
    ]
}

I have a BaseModel that handles the soft deletion overriding the delete method:

class BaseModel(Model):
    archive = BoolYesNoField(db_column="archive", default=False, null=False)
    created = DateTimeField(db_column="created", auto_now_add=True, null=False)
    updated = DateTimeField(db_column="updated", auto_now=True, null=False)

    objects = BaseManager()
    all_objects = BaseManager(alive_only=False)

    def delete(self):
        self.archive = True
        self.save()
        relate_obj_delete(self)

    def hard_delete(self):
        super(Model, self).delete()

    def undelete(self):
        self.archive = False
        self.save()

Manager

class BaseManager(Manager):
    def __init__(self, *args, **kwargs):
        self.alive_only = kwargs.pop("alive_only", True)
        super(BaseManager, self).__init__(*args, **kwargs)

    def get_queryset(self):
        if self.alive_only:
            return BaseQuerySet(self.model).filter(archive=False)
        return BaseQuerySet(self.model)

    def hard_delete(self):
        return self.get_queryset().hard_delete()

AuthorViewSet

class AuthorViewSet(BaseViewSet):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer
    filterset_class = AuthorFilterSet

Serializer

class AuthorSerializer(BaseSerializer):
    books = ResourceRelatedField(many=True, read_only=True)
    included_serializers = {
        "books": BookSerializer,
    }

    class Meta(BaseSerializer.Meta):
        model = Author

If someone could just point me out in the right direction I would be really helpful. There is probably a function that I need to override somewhere but I can't seem to find it.

CodePudding user response:

Your issue is in your serializer. By default Django will use Model._base_manager to fetch related objects and not your custom manager. You need to specify in your nested ResourceRelatedField field which manager you would like to use

class AuthorSerializer(BaseSerializer):
    books = ResourceRelatedField(
        queryset=Book.objects,
        many=True,
        read_only=True
    )
    ...
  • Related