Skip to content

Data Provider

The admin dashboard uses an extended react-admin data provider that communicates with the Django backend REST API. It handles pagination, sorting, filtering, CSRF tokens, and custom business actions.

Standard Methods

The data provider implements all standard react-admin data provider methods:

Method HTTP Description
getList GET /{resource} Paginated list with sort/filter
getOne GET /{resource}/{id} Single record
getMany GET /{resource}?id=1&id=2 Multiple records by ID array
getManyReference GET /{resource}?{fk}={id} List filtered by parent FK
create POST /{resource} Create record
update PUT /{resource}/{id} Update record
updateMany PUT /{resource}/{id} (loop) Batch update
delete DELETE /{resource}/{id} Delete/archive record
deleteMany DELETE /{resource}/{id} (loop) Batch delete

Custom Extensions

The ExtendedDataProvider interface adds three methods for business operations and nested resources:

action(resource, params)

Invoke a business action on a resource (e.g., approve, reverse, waive).

interface ActionParams {
  id: string | number;
  action: string;
  data?: Record<string, unknown>;
}

// Usage
await dataProvider.action("loans", {
  id: loanId,
  action: "approve",
  data: { notes: "Credit check passed" },
});
// POST /api/v1/loans/{id}/approve

getNestedList(params)

Fetch a child resource list scoped to a parent.

interface NestedListParams {
  parentResource: string;
  parentId: string | number;
  childResource: string;
  pagination?: { page: number; perPage: number };
  sort?: { field: string; order: string };
  filter?: Record<string, unknown>;
}

// Usage
const { data, total } = await dataProvider.getNestedList({
  parentResource: "loans",
  parentId: loanId,
  childResource: "payments",
});
// GET /api/v1/loans/{id}/payments

createNested(params)

Create a child resource under a parent.

interface NestedCreateParams {
  parentResource: string;
  parentId: string | number;
  childResource: string;
  data: Record<string, unknown>;
}

// Usage
await dataProvider.createNested({
  parentResource: "borrowers",
  parentId: borrowerId,
  childResource: "addresses",
  data: { street_line_1: "123 Main St", city: "NY" },
});
// POST /api/v1/borrowers/{id}/addresses

Parameter Conversion

Sorting

react-admin sends { field: "name", order: "DESC" }. The provider converts to Django's ordering parameter:

react-admin Django query param
{ field: "name", order: "ASC" } ordering=name
{ field: "name", order: "DESC" } ordering=-name

Pagination

react-admin sends { page: 2, perPage: 25 }. The provider converts to limit/offset:

react-admin Django query param
{ page: 1, perPage: 25 } limit=25&offset=0
{ page: 2, perPage: 25 } limit=25&offset=25

Filtering

Filter objects are converted to query parameters:

Filter Query param
{ status: "active" } status=active
{ id: [1, 2, 3] } id=1&id=2&id=3
{ q: "john" } q=john

Content-Range

List responses include a Content-Range header for total count:

Content-Range: items 0-24/100

The provider parses the total (100) from after the / delimiter.

CSRF Token Handling

All requests include the CSRF token extracted from the csrftoken cookie:

function getCsrfToken(): string {
  const match = document.cookie.match(/csrftoken=([^;]+)/);
  return match ? match[1] : "";
}

The token is sent as the X-CSRFToken header on every request. The cookie is established during the initial session check in the auth provider.

See Also