Unable to form ORM queryset in Django

I am required to include a field present in a parent table to a grandchild table. I have to form a queryset to achieve the mentioned to return list of records for my mobile application. Refer below my models to have a clear picture.

#models.py

class Client(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)
    contact = models.CharField(max_length=10, unique=True)
    email = models.EmailField(null=True)
    address = models.TextField()
    modified_at = models.DateTimeField(auto_now=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'clients'
        ordering = ['id']
        verbose_name = 'Client'
        verbose_name_plural = 'Clients'

    def __str__(self):
        return str(self.id) + ". " + self.name

class Rent(models.Model):
    id = models.AutoField(primary_key=True)
    address = models.TextField()
    rent_amount = models.IntegerField()
    deposit_amount = models.IntegerField()
    rent_date = models.DateField()
    document = models.TextField(null=True)
    remarks = models.TextField(null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)
    client_id = models.IntegerField()

    class Meta:
        db_table = 'rent'
        verbose_name = 'Rent'
        verbose_name_plural = 'Rents'

    def __str__(self):
        return self.id
    
    def get_client_name(self):
        client = Client.objects.get(pk=self.client_id)
        return client.name

class RentSchedule(models.Model):
    id = models.AutoField(primary_key=True)
    rent_due_date = models.DateField()
    paid_amount = models.IntegerField(default=0)
    remaining_amount = models.IntegerField()
    payment_status = models.IntegerField(choices=[(0, 'Unpaid'), (1, 'Paid')], default=0)
    created_at = models.DateTimeField(auto_now_add=True)
    rent_id = models.IntegerField()

    class Meta:
        db_table = 'rent_schedule'
        verbose_name = 'Rent Schedule'
        verbose_name_plural = 'Rent Schedule'

    def __str__(self):
        return self.id
    
    def get_client_name(self):
        rent = Rent.objects.get(pk=self.rent_id)
        client = Client.objects.get(pk=rent.client_id)
        return client.name

Below is my serializer class.

#serializers.py

class RentListSerializer(serializers.ModelSerializer):
    client_name = serializers.CharField(source='get_client_name', required=False)
    remaining_amount = serializers.IntegerField(read_only=True)
    payment_status = serializers.ChoiceField(choices=[0, 1], default=0, write_only=True, error_messages={'invalid_choice': 'Options are 0 or 1'})
    due_date = serializers.DateField(format="%d-%m-%Y", source='rent_due_date', read_only=True)
    date_filter = serializers.DateField(input_formats=['%m-%Y'], default=datetime.now().strftime('%m-%Y'), write_only=True, required=False)
    sort_by_client = serializers.ChoiceField(choices=["asc", "desc"], write_only=True, required=False, error_messages={'invalid_choice': 'Options are asc or desc'})
    sort_by_due_date = serializers.ChoiceField(choices=["asc", "desc"], write_only=True, required=False, error_messages={'invalid_choice': 'Options are asc or desc'})
    sort_by_remaining_amount = serializers.ChoiceField(choices=["asc", "desc"], write_only=True, required=False, error_messages={'invalid_choice': 'Options are asc or desc'})
    
    class Meta:
        model = RentSchedule
        fields = ['id', 'client_name', 'paid_amount', 'remaining_amount', 'due_date', 'payment_status', 'date_filter', 'sort_by_client', 'sort_by_due_date', 'sort_by_remaining_amount']
    
    def to_representation(self, instance):
        representation = super().to_representation(instance)
        representation['payment_status'] = "Paid" if instance.remaining_amount == 0 else "Pending"
        representation.pop('due_date') if instance.remaining_amount == 0 else None
        return representation

Now, finally my class based view is showcased below in which queryset is to be modified.

#views.py

class RentList(GenericAPIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    queryset = RentSchedule.objects.all()
    serializer_class = RentListSerializer

    class CustomPagination(PageNumberPagination):
        page_size = 100
        page_size_query_param = 'page_size'
        max_page_size = 100

        def get_paginated_response(self, data):
            return Response({
                'statusCode': 200,
                'records': self.page.paginator.count,
                'data': data,
                'current_page': self.page.number,
                'total_pages': self.page.paginator.num_pages
            })
        
    pagination_class = CustomPagination

    def initial(self, request, *args, **kwargs):
        super().initial(request, *args, **kwargs)
        self.serializer = self.get_serializer(data=request.data)
        if not self.serializer.is_valid():
            raise ValidationError(detail=self.serializer.errors)

    def filter_queryset(self, queryset, request):
        serializer = self.serializer_class()
        payment_status = request.data.get('payment_status')
        client_name = request.data.get('client_name')
        date_filter = request.data.get('date_filter')
        sort_by_client = request.data.get('sort_by_client')
        sort_by_due_date = request.data.get('sort_by_due_date')
        sort_by_remaining_amount = request.data.get('sort_by_remaining_amount')

"""
This is to be modified as below is an incorrect join ORM.

queryset = queryset.annotate(
    client_name=First(
        Subquery(
            Client.objects.filter(
                id=Subquery(
                    Rent.objects.filter(
                        id=Subquery(
                            RentSchedule.objects.filter(
                                rent_id=OuterRef('id')
                            ).values('rent_id')
                        )
                    ).values('client_id')
                )
            ).values('name')
        )
    )
)
"""

        date_filter = date_filter if date_filter else serializer.fields['date_filter'].get_default()
        month, year = date_filter.split('-')
        queryset = queryset.filter(rent_due_date__month=month, rent_due_date__year=year)

        payment_status = payment_status if payment_status is not None else serializer.fields['payment_status'].get_default()
        queryset = queryset.filter(payment_status=payment_status)

        if client_name:
            queryset = queryset.filter(rent_id__in=Rent.objects.filter(client_id__in=Client.objects.filter(name__icontains=client_name).values('id')).values('id'))

        if sort_by_client:
            if sort_by_client.lower() == 'asc':
                queryset = queryset.order_by('client_name')
            elif sort_by_client.lower() == 'desc':
                queryset = queryset.order_by('-client_name')

        if sort_by_due_date:
            if sort_by_due_date.lower() == 'asc':
                queryset = queryset.order_by('rent_due_date')
            elif sort_by_due_date.lower() == 'desc':
                queryset = queryset.order_by('-rent_due_date')
        
        if sort_by_remaining_amount:
            if sort_by_remaining_amount.lower() == 'asc':
                queryset = queryset.order_by('remaining_amount')
            elif sort_by_remaining_amount.lower() == 'desc':
                queryset = queryset.order_by('-remaining_amount')

        return queryset

    def post(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset(), request)
        paginator = self.pagination_class()
        paginated_queryset = paginator.paginate_queryset(queryset, request, view=self)
        serializer = self.get_serializer(paginated_queryset, many=True)
        return paginator.get_paginated_response(serializer.data)
    
    def handle_exception(self, exc):
        if isinstance(exc, ValidationError):
            response = Response(
                data={
                    "status_code": 400,
                    "message": exc.detail
                },
                status=400
            )
            return response
        return super().handle_exception(exc)

My objective is to include name field from Client model which is the grandparent model to the queryset in mentioned in the comments. I want it to go by alias client_name such that it appears in the records by that key.

queryset = RentSchedule.objects.all()

Since, the models RentSchedule and Rent don’t have a foreignkey datatype due to my project limitations, I couldn’t use queryset’s select_related method to achieve same. I can only think of annonate method which would require complex subquery.

How do I achieve this so I can sort the queryset via client_name field in ‘asc’ or ‘desc’ order?

Thank you all in advance.