npm.io
0.29.5 • Published 18h ago

drf-react-by-schema

Licence
MIT
Version
0.29.5
Deps
0
Size
1010 kB
Vulns
0
Weekly
0

DRF And React By Schema - React

DRF and React by Schema is a pair of packages — drf-react-by-schema-django (server) and drf-react-by-schema (client) — that add schema-driven CRUD to a Django REST Framework backend. Django describes each model; React renders forms, validation, lists and detail views from that description.

How it works

  • Django/DRF owns the data model. Models, serializers and viewsets stay on the server. drf-react-by-schema-django derives a per-model schema (field types, labels, required/read-only flags, choices, relations, validators, layout) and serves it through OPTIONS, or writes it to disk with the sync_react command.
  • React renders from the schema. drf-react-by-schema reads the schema and builds the matching UI: a field type selects the form widget, the DataGrid cell, its inline editor and the yup validation rule. No per-model form code.
  • One source of truth. Changing a Django model is enough to change the React forms, columns and validation. Widgets, layout, labels and validation can still be customized per app.

Published packages: npm drf-react-by-schema and PyPI drf-react-by-schema.

API reference

Every exported component (purpose and props), the full useAPIWrapper() API (data, auth, form state, dialogs, feedback), the shared prop building blocks (fieldsLayout, fieldsProps, sumRows, actions, …) and the utility functions are documented in docs/API_REFERENCE.md.

Consuming apps must use useAPIWrapper(). The lower-level useDRFReactBySchema() is internal, is not exported from the package entry and must not be used by app code.

Field types & widgets

Every schema field type maps to a specific widget. This includes the standard types (text, number, choices, dates, booleans, files, images, …) and the PostGIS geometry fields (point, polygon, multipoint, multipolygon, geometrycollection), which render an interactive Leaflet map picker/drawer with a read-only thumbnail map in the DataGrid.

See the complete table of field types and their widgets (including the geometry behaviours — add/move/remove rules, GeoJSON text sync and fallbacks) in docs/FIELD_TYPES.md.

Conditional visibility (conditional_visible)

A field can be shown/hidden from the <Form>/FormBySchema and the DataGrid inline editor depending on the value of other fields. While hidden, its value is cleared on save (and in the form). The schema key conditional_visible, produced by the Django package's custom fields, accepts these shapes:

  • a single [sourceField, sourceValue] pair — a single condition, e.g. ["type", "book"];

  • a plain array of conditions — combined with OR (show if any matches), the legacy fallback;

  • an explicit { operator: 'AND' | 'OR', conditions: [...] } expression for arbitrary, parenthesised logic. conditions may mix pairs and nested expressions, e.g. show isbn only when the record type is book and the format is either hardcover or paperback:

    {
      "operator": "AND",
      "conditions": [
        ["type", "book"],
        {
          "operator": "OR",
          "conditions": [
            ["format", "hardcover"],
            ["format", "paperback"]
          ]
        }
      ]
    }

A plain array of conditions is always OR; use an explicit { operator: 'AND', ... } when every condition must hold. Combined with ui_required, a conditionally visible field is required only while it is actually shown.

Scoping autocomplete options (optionsACQueryParams)

The package loads relation-field options automatically. To send static query params with those fetches — e.g. to make a backend filter_by_callback scope a relation to a parent record — pass optionsACQueryParams:

const params = ufpaId ? [`ufpa_id=${ufpaId}`] : undefined;

<Form
  model="linha_de_base"
  optionsACQueryParams={
    params && {
      responsavel: params,                              // a top-level relation field
      formas_acesso_terra: { em_nome_de_quem: params }, // an inline formset's child field
    }
  }
/>

A relation field maps to a string[]; a writable inline formset maps to a nested record keyed by its child fields under its parent field key. It works on Form, FormBySchema, InlineFormsetFieldBySchema, the grids (GenericModelList, GenericRelatedModelList, DataGridBySchemaEditable) and the related-edit dialog (DialogFormBySchema). It is the static counterpart of the per-row filterOptionsAC. Full details: docs/API_REFERENCE.md §4.16.

Localization & theming

User-facing strings (geometry picker, form/dialog action buttons, …) are exposed through the MUI theme (theme.texts), so you can localize every widget in your own theme.ts — no provider changes. The package ships with sensible defaults and also localizes the MUI components it renders (DataGrid, date pickers) to pt-BR.

See the full reference (namespaces, precedence, MUI locale setup, custom markers) in docs/localization.md.

Authentication, password reset & e-mail

The package ships ready-made pieces for a forgot/change password flow over the JWT + simplejwt stack: the ForgotPasswordForm and ChangePasswordForm components, plus requestPasswordReset, validatePasswordReset, confirmPasswordReset and changePassword helpers on useAPIWrapper(). They talk to the endpoints provided by the Django package (password_reset/request|validate|confirm, my_account/change_password).

See how to wire them up, the server contract, and how to set up e-mail/SMTP for the reset link in docs/password-reset-and-email.md.

Getting started

  1. Build the Django project and models (guide: https://pypi.org/project/drf-react-by-schema/).

  2. Create the frontend folder that will hold the React app.

  3. Install the required peer dependencies:

yarn add @emotion/react@^11 @emotion/styled@^11 @hookform/resolvers@^3 @mui/icons-material@^6 @mui/material@^6 @mui/x-data-grid@^7 @mui/x-date-pickers@^7 axios@^1 dayjs@^1 react@^18 react-dom@^18 react-hook-form@^7 react-number-format@^5 string-mask@^0.3.0 yup@^1

Install the optional widget peers only for the features you use:

# geometry (PostGIS) pickers
yarn add leaflet@^1.9 react-leaflet@^5 leaflet-draw@^1.0.4
# rich-text fields (model_html)
yarn add @tiptap/react@^3 @tiptap/starter-kit@^3 dompurify@^3
  1. Install drf-react-by-schema:
yarn add drf-react-by-schema
  1. Wrap the app with DRFReactBySchemaProvider, passing the Django endpoints and the theme:
// App.tsx
import { DRFReactBySchemaProvider } from 'drf-react-by-schema';
import * as schemas from './drfReactBySchema';
import { paginationConfig } from './drfReactBySchema/pagination';
import { theme } from './theme';

export default function App() {
  return (
    <DRFReactBySchemaProvider
      serverEndPoint={{
        url: 'http://localhost:8000',
        apiTokenUrl: 'http://localhost:8000/api/token/',
      }}
      schemas={schemas}
      pagination={paginationConfig}
      theme={theme}>
      <YourWonderfulApp />
    </DRFReactBySchemaProvider>
  );
}

schemas and paginationConfig are generated by sync_react (see below) and are optional: without them the provider fetches each schema with OPTIONS and uses the package's default pagination.

  1. Build the pages from the package components. Start with a list and a form:
<GenericModelList model="produto" paginationMode="server" />
<Form model="produto" objId={id} />

See docs/API_REFERENCE.md for every component and the useAPIWrapper() surface.

Syncing React with Django

drf-react-by-schema-django ships the sync_react management command. Add a script to package.json, using the Python executable of your virtual environment:

"scripts": {
    "sync-react": "cd ../ && ./venv/bin/python manage.py sync_react"
}

Or, with the virtualenv activated:

"scripts": {
    "sync-react": "cd ../backend && python manage.py sync_react"
}

It writes the src/drfReactBySchema/ folder (path configurable through DRF_REACT_BY_SCHEMA['REACT_APP_DIR']):

  • schemas/<Model>Schema.json — one schema per model;
  • types.ts — TypeScript interfaces and enums for the models;
  • optionsGetters.ts — label helpers for the generated enums;
  • index.ts — one <Model>Schema loader per model, imported as a single object (import * as schemas);
  • pagination.ts — the paginationConfig object.

Import model types from drfReactBySchema/types to type your components and data.

Keywords