CountAdapter

Base class for pluggable count extraction strategies in ApiBackend.

  1. Overview

Overview

Responsible for answering one question: how many records are there in total? This is separate from pagination (which answers “how do I get the next page?” — see :class:~clearskies.backends.adapters.PaginationAdapter).

Different APIs communicate counts in completely different ways — some use response headers, some embed counts in the response body, and some don’t provide counts at all. Subclass CountAdapter and override extract_count to handle your API’s counting style.

clearskies ships with one concrete implementation:

  • :class:~clearskies.backends.adapters.HeaderCountAdapter — reads X-Total-Count, X-Total, and X-Total-Pages response headers (the default for ApiBackend)

Implementing a custom adapter

import clearskies


class BodyCountAdapter(clearskies.backends.adapters.CountAdapter):
    def extract_count(self, response_data, response_headers, query=None):
        if isinstance(response_data, dict):
            total = response_data.get("meta", {}).get("total")
            if total is not None:
                return (int(total), None)
        return (None, None)

Attach it to an ApiBackend:

backend = clearskies.backends.ApiBackend(
    base_url="https://api.example.com",
    count_adapter=BodyCountAdapter(),
)

Using a callable

For simple cases a plain callable may be supplied instead of a full subclass. The callable receives (response_headers, response_data) and should return a tuple of (total_count, total_pages) where either value can be None:

backend = clearskies.backends.ApiBackend(
    base_url="https://api.example.com",
    count_adapter=lambda headers, data: (
        int(headers["X-My-Total"]) if headers and "X-My-Total" in headers else None,
        None,
    ),
)