From 0d7a00395565827a2985591b319d07005659fa43 Mon Sep 17 00:00:00 2001 From: SanthoshIruthayaraj Date: Fri, 27 Feb 2026 16:12:12 +0530 Subject: [PATCH] Task(1006328): Added sample --- .../README.md | 176 ++++++++++++++++ .../client/README.md | 73 +++++++ .../client/eslint.config.js | 23 +++ .../client/index.html | 14 ++ .../client/package.json | 34 ++++ .../client/public/vite.svg | 1 + .../client/src/App.css | 0 .../client/src/App.tsx | 25 +++ .../client/src/assets/react.svg | 1 + .../client/src/components/OrdersGrid.tsx | 163 +++++++++++++++ .../client/src/index.css | 10 + .../client/src/main.tsx | 10 + .../client/src/services/apiClient.ts | 190 ++++++++++++++++++ .../client/tsconfig.app.json | 28 +++ .../client/tsconfig.json | 7 + .../client/tsconfig.node.json | 26 +++ .../client/vite.config.ts | 7 + .../django_server/library/__init__.py | 0 .../django_server/library/admin.py | 3 + .../django_server/library/apps.py | 6 + .../library/migrations/0001_initial.py | 34 ++++ .../library/migrations/__init__.py | 0 .../django_server/library/models.py | 27 +++ .../django_server/library/serializers.py | 24 +++ .../django_server/library/views.py | 80 ++++++++ .../django_server/manage.py | 22 ++ .../django_server/requirements.txt | 6 + .../django_server/server/__init__.py | 0 .../django_server/server/asgi.py | 16 ++ .../django_server/server/settings.py | 168 ++++++++++++++++ .../django_server/server/urls.py | 29 +++ .../django_server/server/wsgi.py | 16 ++ 32 files changed, 1219 insertions(+) create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/README.md create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/README.md create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/eslint.config.js create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/index.html create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/package.json create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/public/vite.svg create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/App.css create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/App.tsx create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/assets/react.svg create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/components/OrdersGrid.tsx create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/index.css create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/main.tsx create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/services/apiClient.ts create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.app.json create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.json create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.node.json create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/vite.config.ts create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/__init__.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/admin.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/apps.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/migrations/0001_initial.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/migrations/__init__.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/models.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/serializers.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/views.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/manage.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/requirements.txt create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/__init__.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/asgi.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/settings.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/urls.py create mode 100644 connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/wsgi.py diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/README.md b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/README.md new file mode 100644 index 0000000..179811b --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/README.md @@ -0,0 +1,176 @@ +# Syncfusion React Grid with Django REST Framework (Custom Binding) + Microsoft SQL Server + +A clean, production‑oriented example showing how to connect **Syncfusion React Grid** to **Django REST Framework (DRF)** and **SQL Server** using **Custom Binding**. Supports server‑driven paging, sorting, filtering, searching, and full CRUD with a REST‑native contract (`GET` with query params + `POST/PUT/DELETE` for edits). + +## Key Features + +- **Custom Binding Pattern**: Manual control of REST requests using `dataStateChange` & `dataSourceChanged` +- **DRF Query-String Model**: Native `page`, `page_size`, `ordering`, `search`, and flexible filter operators +- **SQL Server Integration**: `mssql-django` + `pyodbc` with migrations +- **Advanced Grid Behavior**: Excel-style filtering, multi-select date filtering, paging, sorting, searching +- **Full CRUD**: POST, PUT, DELETE via DRF `ModelViewSet` +- **CORS Ready**: Seamless local React ↔ Django development + +## Prerequisites + +- **Node.js** LTS (20+) with npm/yarn +- **React** 18+ (Vite) +- **Python** 3.11+ +- **Django** 5.2+, **DRF**, **django-filter**, **corsheaders** +- **Microsoft SQL Server** (works with LocalDB or remote instances) + +--- + +## Quick Start + +### 1) Clone the repository +```bash +git clone +cd +``` + +--- + +## 2) Backend (Django + DRF + SQL Server) + +Create a virtual environment & install packages: + +```bash +python -m venv .venv +# Windows +.venv\Scripts\activate +# macOS/Linux +# source .venv/bin/activate + +pip install django djangorestframework django-filter django-cors-headers mssql-django pyodbc +``` + +**Configure SQL Server in `settings.py`:** + +```python +DATABASES = { + "default": { + "ENGINE": "mssql", + "NAME": "LibraryDB", + "USER": "django_user", + "PASSWORD": "Django@123", + "HOST": "(localdb)\MSSQLLocalDB", + "OPTIONS": { + "driver": "ODBC Driver 18 for SQL Server", + "trustServerCertificate": "yes", + }, + } +} +``` + +Enable CORS: + +```python +CORS_ALLOWED_ORIGINS = [ + "http://localhost:5173", +] +``` + +Run migrations & start API: + +```bash +python manage.py makemigrations +python manage.py migrate +python manage.py runserver 8000 +``` + +API available at: +`http://localhost:8000/api/lendings/` + +--- + +## 3) Frontend (React + Syncfusion Grid + Custom Binding) + +Install packages: + +```bash +npm install +``` + +Start the app: + +```bash +npm run dev +``` + +Navigate to `http://localhost:5173`. + +### Grid architecture: + +- **Reads**: `dataStateChange → fetchLendings(state)` → DRF (`GET /lendings/?page=…&page_size=…&ordering=…`) +- **CRUD**: `dataSourceChanged → POST/PUT/DELETE` → DRF +- **Excel Filter UI**: filter-choice requests receive lightweight `result` arrays + +The client uses a shared service (`apiClient.ts`) to convert Grid state into DRF query parameters including: + +- `page`, `page_size` +- `ordering` (`author_name,-borrowed_date`) +- `search` +- field filters using operators (`__icontains`, `__gte`, `__lte`, `__in`, etc.) +- CSV date-set filtering using `__in=YYYY-MM-DD,YYYY-MM-DD,…` + +--- + +## Project Layout + +| File/Folder | Purpose | +|-------------|---------| +| `django_server/settings.py` | SQL Server, DRF, CORS configuration | +| `django_server/urls.py` | Registers `lendings/` ViewSet | +| `library/models.py` | `BookLending` model | +| `library/serializers.py` | Serializer + UTC Zulu date formatting | +| `library/views.py` | REST ViewSet with ordering/search/filter/paging + `{ result, count }` | +| `client/src/services/apiClient.ts` | Custom Binding request builder & CRUD | +| `client/src/components/OrdersGrid.tsx` | Grid wired to DRF via Custom Binding | +| `client/src/index.css` | Syncfusion Bootstrap 5.3 theme imports | + +--- + +## Common Tasks + +### Add +1. Toolbar → **Add** +2. Fill fields → **Save** +Grid triggers `dataSourceChanged → POST`. + +### Edit +1. Select row → **Edit** +2. Modify → **Update** +Grid triggers `PUT`. + +### Delete +1. Select → **Delete** +2. Confirm +Grid triggers `DELETE`. + +### Filtering / Searching / Sorting +- Excel filter menu with operators & date multi-select +- Search bar queries DRF `SearchFilter` +- Header click sorting → `ordering` query param + +--- + +## Troubleshooting + +**ODBC / SQL Errors** +- Install **ODBC Driver 18 for SQL Server** +- Ensure driver architecture matches Python (64‑bit recommended) + +**CORS failures** +- Ensure `corsheaders` is in `INSTALLED_APPS` + middleware +- Confirm `http://localhost:5173` in `CORS_ALLOWED_ORIGINS` + +**Filter/Date issues** +- DRF uses strict ISO formats; serializers convert all dates to `YYYY-MM-DDT00:00:00Z` +- Multi-select dates appear as `__in=2026-01-01,2026-01-05` + +**Pagination not working** +- Ensure frontend sends `skip` & `take` +- Backend must read `page` & `page_size` + +--- diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/README.md b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/README.md new file mode 100644 index 0000000..d2e7761 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/README.md @@ -0,0 +1,73 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: + +```js +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + + // Remove tseslint.configs.recommended and replace with this + tseslint.configs.recommendedTypeChecked, + // Alternatively, use this for stricter rules + tseslint.configs.strictTypeChecked, + // Optionally, add this for stylistic rules + tseslint.configs.stylisticTypeChecked, + + // Other configs... + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` + +You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: + +```js +// eslint.config.js +import reactX from 'eslint-plugin-react-x' +import reactDom from 'eslint-plugin-react-dom' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + // Enable lint rules for React + reactX.configs['recommended-typescript'], + // Enable lint rules for React DOM + reactDom.configs.recommended, + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/eslint.config.js b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/eslint.config.js new file mode 100644 index 0000000..5e6b472 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/index.html b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/index.html new file mode 100644 index 0000000..8e1f259 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/index.html @@ -0,0 +1,14 @@ + + + + + + + + client + + +
+ + + diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/package.json b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/package.json new file mode 100644 index 0000000..3f6d13e --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/package.json @@ -0,0 +1,34 @@ +{ + "name": "client", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "start": "vite", + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@syncfusion/ej2-base": "^32.2.3", + "@syncfusion/ej2-data": "^32.2.3", + "@syncfusion/ej2-react-grids": "^32.2.3", + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/node": "^24.10.1", + "@types/react": "^19.2.5", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "typescript": "~5.9.3", + "typescript-eslint": "^8.46.4", + "vite": "^7.2.4" + } +} diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/public/vite.svg b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/App.css b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/App.css new file mode 100644 index 0000000..e69de29 diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/App.tsx b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/App.tsx new file mode 100644 index 0000000..b8b384c --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/App.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { registerLicense } from '@syncfusion/ej2-base'; +import OrdersGrid from './components/OrdersGrid'; +import './App.css'; + +const licenseKey = (import.meta as { env: Record }).env + .VITE_SYNCFUSION_LICENSE_KEY; + +if (licenseKey) { + registerLicense(licenseKey); +} + +const App: React.FC = () => { + return ( +
+
+

Library Lending Records

+

Custom data binding with Syncfusion React Grid and Django REST Framework

+
+ +
+ ); +}; + +export default App; \ No newline at end of file diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/assets/react.svg b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/components/OrdersGrid.tsx b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/components/OrdersGrid.tsx new file mode 100644 index 0000000..21c8e7e --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/components/OrdersGrid.tsx @@ -0,0 +1,163 @@ +import React, { useEffect, useRef } from 'react'; +import { + GridComponent, + ColumnsDirective, + ColumnDirective, + Inject, + Page, + Sort, + Filter, + Edit, + Toolbar, + Search, + type DataSourceChangedEventArgs, + type DataStateChangeEventArgs, + type EditSettingsModel, + type ToolbarItems, +} from '@syncfusion/ej2-react-grids'; +import { + createLending, + deleteLending, + fetchLendings, + updateLending, + type LendingRecord, +} from '../services/apiClient'; +import { Query } from '@syncfusion/ej2-data'; + +const OrdersGrid: React.FC = () => { + const gridRef = useRef(null); + + const pageSettings = { pageSize: 10, pageSizes: [10, 20, 50, 100] }; + const toolbar: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel', 'Search']; + const editSettings: EditSettingsModel = { + allowAdding: true, + allowEditing: true, + allowDeleting: true, + }; + + const validationRules = { + required: true, + }; + + useEffect(() => { + const initialState = { + skip: 0, + take: 10, + } as DataStateChangeEventArgs; + + void handleDataStateChange(initialState); + }, []); + + /** + * Loads data when Grid state changes (paging/sorting/filtering/searching). + */ + const handleDataStateChange = async (args: DataStateChangeEventArgs) => { + const gridState = { + skip: args.skip, + take: args.take, + sorted: args.sorted, + where: args.where, + search: args.search, + } as DataStateChangeEventArgs; + + const res = await fetchLendings(gridState); + + if ( + args.action && args.dataSource && + (args.action.requestType === 'filterchoicerequest' || + args.action.requestType === 'filterSearchBegin' || + args.action.requestType === 'stringfilterrequest') + ) { + args.dataSource(res.result); + } else if (gridRef.current) { + gridRef.current.dataSource = res; + } + }; + + /** + * Handles CRUD actions (add/edit/delete) using custom data binding. + */ + const handleDataSourceChanged = async (args: DataSourceChangedEventArgs) => { + if (args.action === 'add' && args.requestType === 'save') { + await createLending(args.data as LendingRecord); + } + + if (args.action === 'edit' && args.requestType === 'save') { + await updateLending(args.data as LendingRecord); + } + + if (args.requestType === 'delete') { + await deleteLending((args.data as LendingRecord[])[0].record_id); + } + + args.endEdit?.(); + }; + + const lendingStatusParams = { params: { dataSource: ['Borrowed', 'Overdue', 'Returned'], query: new Query() } }; + + return ( +
+ + + + + + + + + + + + + + + + + + +
+ ); +}; + +export default OrdersGrid; diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/index.css b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/index.css new file mode 100644 index 0000000..af7eb16 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/index.css @@ -0,0 +1,10 @@ +@import '../node_modules/@syncfusion/ej2-base/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-calendars/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-popups/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-notifications/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-react-grids/styles/material.css'; \ No newline at end of file diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/main.tsx b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/main.tsx new file mode 100644 index 0000000..bef5202 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/services/apiClient.ts b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/services/apiClient.ts new file mode 100644 index 0000000..2ffcb56 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/src/services/apiClient.ts @@ -0,0 +1,190 @@ +// api/services/apiClient.ts +import { DataUtil } from '@syncfusion/ej2-data'; +import type { DataStateChangeEventArgs } from '@syncfusion/ej2-react-grids'; + +const API_BASE_URL = 'http://localhost:8000/api'; + +const request = async (path: string, options: RequestInit = {}): Promise => { + const res = await fetch(`${API_BASE_URL}${path}`, { + headers: { 'Content-Type': 'application/json' }, + ...options, + }); + if (res.status === 204) return null as T; + return res.json() as Promise; +}; + +// Keep ":" unencoded in the final query string (DevTools readability) +const keepColonsReadable = (qs: string): string => qs.replace(/%3A/gi, ':'); + +// Flatten nested predicates +const flatten = (items: Predicate[] = []): Predicate[] => + items.flatMap((p) => (p.predicates?.length ? flatten(p.predicates) : [p])); + +// DRF operator suffix map (non-date multi-select fields still use these) +const OP_SUFFIX: Record = { + contains: '__icontains', + startswith: '__istartswith', + endswith: '__iendswith', + greaterthan: '__gt', + greaterthanorequal: '__gte', + lessthan: '__lt', + lessthanorequal: '__lte', +}; + +// Your three date columns are always treated as multi-select +const dateFields = new Set(['borrowed_date', 'expected_return_date', 'actual_return_date']); + +// Normalize any date-like into YYYY-MM-DD (UTC), safe against TZ offsets +const toDay = (v: unknown): string | null => { + if (v == null) return null; + const d = typeof v === 'string' || v instanceof Date ? new Date(v as any) : null; + return d && !isNaN(d.getTime()) ? d.toISOString().slice(0, 10) : null; +}; + +const buildFilterParams = (predicates: Predicate[] | undefined, params: URLSearchParams) => { + if (!predicates?.length) return; + + // Collectors + const equalsByField = new Map(); // non-date equals -> later field / field__in + const daySetByDateField = new Map>(); // date fields -> set of YYYY-MM-DD + + const addDay = (field: string, v: unknown) => { + const day = toDay(v); + if (!day) return; + const set = daySetByDateField.get(field) ?? new Set(); + set.add(day); + daySetByDateField.set(field, set); + }; + + for (const p of flatten(predicates)) { + const field = p.field; + if (!field || p.value === undefined || p.value === null) continue; + + const op = String(p.operator || 'equal').toLowerCase(); + + // Handling for date fields + if (dateFields.has(field)) { + if (Array.isArray(p.value)) { + for (const v of p.value) addDay(field, v); + } else if (op === 'equal' || op === 'lessthan') { + addDay(field, p.value); + } + // Skip emitting any other operators for these fields. + continue; + } + + // Non-date fields + if (Array.isArray(p.value)) { + if (op === 'equal') { + const list = equalsByField.get(field) ?? []; + list.push(...p.value.map(String)); + equalsByField.set(field, list); + } else { + params.set(`${field}__in`, p.value.map(String).join(',')); + } + continue; + } + + if (op === 'equal') { + const list = equalsByField.get(field) ?? []; + list.push(String(p.value)); + equalsByField.set(field, list); + continue; + } + + const suffix = OP_SUFFIX[op]; + if (suffix) params.set(`${field}${suffix}`, String(p.value)); + } + + // Emit equals as field or field__in for non-date fields + for (const [field, values] of equalsByField.entries()) { + params.set(values.length === 1 ? field : `${field}__in`, values.join(',')); + } + + // Emit __in for date multi-select + for (const [field, set] of daySetByDateField.entries()) { + if (set.size) params.set(`${field}__in`, [...set].join(',')); + } +}; + +// Builds DRF query params from Syncfusion Grid state. +export const buildQueryParams = (state: DataStateChangeEventArgs): URLSearchParams => { + const params = new URLSearchParams(); + const take = state.take ?? 10; + const skip = state.skip ?? 0; + const page = Math.floor(skip / take) + 1; + + params.set('page', String(page)); + params.set('page_size', String(take)); + + const sorted = (state.sorted || []) as SortDescriptor[]; + if (sorted.length) { + params.set( + 'ordering', + sorted.map((s) => (s.direction === 'descending' ? `-${s.name}` : s.name)).join(',') + ); + } + + const search = (state.search || []) as SearchDescriptor[]; + if (search.length) params.set('search', search.map((s) => s.key).join(' ')); + + buildFilterParams(state.where as Predicate[] | undefined, params); + + return params; +}; + +/** Fetch lending records using DRF pagination format. **/ +export const fetchLendings = async (state: DataStateChangeEventArgs) => { + const query = keepColonsReadable(buildQueryParams(state).toString()); + const res = await request<{ result?: LendingRecord[]; count: number }>(`/lendings/?${query}`); + + return { + result: (DataUtil as any).parse.parseJson(res.result) ?? [], + count: res.count ?? 0, + }; +}; + +/** CRUD **/ +export const createLending = (payload: LendingRecord) => + request('/lendings/', { method: 'POST', body: JSON.stringify(payload) }); + +export const updateLending = (payload: LendingRecord) => + request(`/lendings/${payload.record_id}/`, { + method: 'PUT', + body: JSON.stringify(payload), + }); + +export const deleteLending = (recordId: number) => + request(`/lendings/${recordId}/`, { method: 'DELETE' }); + +/** Types */ +export interface LendingRecord { + record_id: number; + isbn_number: string; + book_title: string; + author_name: string; + genre: string; + borrower_name: string; + borrower_email: string; + borrowed_date: string; + expected_return_date: string; + actual_return_date?: string | null; + lending_status: string; +} + +interface SortDescriptor { + name: string; + direction: 'ascending' | 'descending'; +} + +interface SearchDescriptor { + key: string; +} + +interface Predicate { + field?: string; + operator?: string; + value?: unknown; + predicates?: Predicate[]; + condition?: 'and' | 'or'; +} \ No newline at end of file diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.app.json b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.app.json new file mode 100644 index 0000000..a9b5a59 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.app.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "types": ["vite/client"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.json b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.node.json b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.node.json new file mode 100644 index 0000000..8a67f62 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/tsconfig.node.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "types": ["node"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/vite.config.ts b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/vite.config.ts new file mode 100644 index 0000000..8b0f57b --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/client/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +}) diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/__init__.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/admin.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/apps.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/apps.py new file mode 100644 index 0000000..c33ac9c --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class LibraryConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'library' diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/migrations/0001_initial.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/migrations/0001_initial.py new file mode 100644 index 0000000..aaf9782 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/migrations/0001_initial.py @@ -0,0 +1,34 @@ +# Generated by Django 5.2.10 on 2026-01-22 12:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='BookLending', + fields=[ + ('record_id', models.AutoField(primary_key=True, serialize=False)), + ('book_title', models.CharField(max_length=255)), + ('isbn_number', models.CharField(db_index=True, max_length=32)), + ('author_name', models.CharField(max_length=255)), + ('genre', models.CharField(max_length=100)), + ('borrower_name', models.CharField(max_length=255)), + ('borrower_email', models.EmailField(max_length=254)), + ('borrowed_date', models.DateField()), + ('expected_return_date', models.DateField()), + ('actual_return_date', models.DateField(blank=True, null=True)), + ('lending_status', models.CharField(max_length=20)), + ], + options={ + 'ordering': ['-borrowed_date'], + 'indexes': [models.Index(fields=['book_title'], name='library_boo_book_ti_ead89d_idx'), models.Index(fields=['author_name'], name='library_boo_author__eab069_idx'), models.Index(fields=['genre'], name='library_boo_genre_79218d_idx'), models.Index(fields=['lending_status'], name='library_boo_lending_f42c71_idx')], + }, + ), + ] diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/migrations/__init__.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/models.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/models.py new file mode 100644 index 0000000..d2cef21 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/models.py @@ -0,0 +1,27 @@ +from django.db import models + +class BookLending(models.Model): + """Represents a library lending record.""" + record_id = models.AutoField(primary_key=True) # Unique identifier + book_title = models.CharField(max_length=255) + isbn_number = models.CharField(max_length=32, db_index=True) + author_name = models.CharField(max_length=255) + genre = models.CharField(max_length=100) + borrower_name = models.CharField(max_length=255) + borrower_email = models.EmailField() + borrowed_date = models.DateField() + expected_return_date = models.DateField() + actual_return_date = models.DateField(null=True, blank=True) # optional + lending_status = models.CharField(max_length=20) # Borrowed, Returned, Overdue + + class Meta: + indexes = [ + models.Index(fields=["book_title"]), + models.Index(fields=["author_name"]), + models.Index(fields=["genre"]), + models.Index(fields=["lending_status"]), + ] + ordering = ["-borrowed_date"] + + def __str__(self): + return f"{self.book_title} ({self.isbn_number}) - {self.borrower_name}" diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/serializers.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/serializers.py new file mode 100644 index 0000000..9bad9b5 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/serializers.py @@ -0,0 +1,24 @@ + +from rest_framework import serializers +from .models import BookLending + + +class ZuluDateField(serializers.DateField): + """Date field serialized as YYYY-MM-DDT00:00:00Z.""" + + def to_representation(self, value): + if value is None: + return None + return f"{value:%Y-%m-%d}T00:00:00Z" + + +class BookLendingSerializer(serializers.ModelSerializer): + """Serializer for BookLending records.""" + + borrowed_date = ZuluDateField() + expected_return_date = ZuluDateField() + actual_return_date = ZuluDateField(allow_null=True, required=False) + + class Meta: + model = BookLending + fields = "__all__" diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/views.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/views.py new file mode 100644 index 0000000..f7c0bc9 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/library/views.py @@ -0,0 +1,80 @@ +# library/views.py +from rest_framework import viewsets +from rest_framework.filters import OrderingFilter, SearchFilter +from rest_framework.response import Response +from django_filters.rest_framework import DjangoFilterBackend +from django_filters import rest_framework as filters + +from .models import BookLending +from .serializers import BookLendingSerializer + +class DateInFilter(filters.BaseInFilter, filters.DateFilter): + """Accepts CSV dates -> applies __in for DateField.""" + pass + +class BookLendingFilterSet(filters.FilterSet): + borrowed_date__in = DateInFilter(field_name='borrowed_date', lookup_expr='in') + expected_return_date__in = DateInFilter(field_name='expected_return_date', lookup_expr='in') + actual_return_date__in = DateInFilter(field_name='actual_return_date', lookup_expr='in') + + class Meta: + model = BookLending + fields = { + "record_id": ["exact", "in"], + "book_title": ["exact", "in", "icontains", "istartswith", "iendswith"], + "isbn_number": ["exact", "in", "icontains", "istartswith", "iendswith"], + "author_name": ["exact", "in", "icontains", "istartswith", "iendswith"], + "genre": ["exact", "in", "icontains", "istartswith", "iendswith"], + "borrower_name": ["exact", "in", "icontains", "istartswith", "iendswith"], + "borrower_email": ["exact", "in", "icontains", "istartswith", "iendswith"], + "borrowed_date": ["exact", "gt", "gte", "lt", "lte"], + "expected_return_date": ["exact", "gt", "gte", "lt", "lte"], + "actual_return_date": ["exact", "gt", "gte", "lt", "lte"], + "lending_status": ["exact", "in", "icontains", "istartswith", "iendswith"], + } + +class BookLendingViewSet(viewsets.ModelViewSet): + """ + REST ViewSet for BookLending with standard DRF request/response formats. + """ + + queryset = BookLending.objects.all() + serializer_class = BookLendingSerializer + + filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] + filterset_class = BookLendingFilterSet + + search_fields = [ + "record_id", + "isbn_number", + "book_title", + "author_name", + "genre", + "borrower_name", + "borrower_email", + "lending_status", + ] + + def list(self, request, *args, **kwargs): + """Return paginated list: { result, count } honoring page/page_size.""" + queryset = self.filter_queryset(self.get_queryset()) + + page = int(request.query_params.get("page")) + page_size = int(request.query_params.get("page_size")) + + total = queryset.count() + offset = (page - 1) * page_size + serializer = self.get_serializer(queryset[offset: offset + page_size], many=True) + return Response({ "result": serializer.data, "count": total }) + + def create(self, request, *args, **kwargs): + """Create a new lending record and return the created object.""" + return super().create(request, *args, **kwargs) + + def update(self, request, *args, **kwargs): + """Update a lending record and return the updated object.""" + return super().update(request, *args, **kwargs) + + def destroy(self, request, *args, **kwargs): + """Delete a lending record and return 204 No Content.""" + return super().destroy(request, *args, **kwargs) diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/manage.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/manage.py new file mode 100644 index 0000000..8b46ee6 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/requirements.txt b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/requirements.txt new file mode 100644 index 0000000..4cfac70 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/requirements.txt @@ -0,0 +1,6 @@ +Django==4.2.0 +djangorestframework==3.14.0 +django-cors-headers==4.3.0 +django-filter==24.2 +mssql-django==1.4 +pyodbc==5.2.0 diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/__init__.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/asgi.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/asgi.py new file mode 100644 index 0000000..cb95f8e --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for server project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings') + +application = get_asgi_application() diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/settings.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/settings.py new file mode 100644 index 0000000..7703364 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/settings.py @@ -0,0 +1,168 @@ +""" +Django settings for server project. + +Generated by 'django-admin startproject' using Django 5.2.10. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.2/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-^j7x^2o4mt*mh_sf4t8%i#y&e6x%q4ifj=@e-k^yadd18@xy9)' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + + +INSTALLED_APPS = [ + "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", + "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + # third-party + "rest_framework", "django_filters", "corsheaders", + # local + "library", +] + +MIDDLEWARE = [ + "corsheaders.middleware.CorsMiddleware", + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", +] + +# Allow Angular dev origin +CORS_ALLOWED_ORIGINS = [ + "http://localhost:5173", +] + +# MS SQL Server database +DATABASES = { + "default": { + "ENGINE": "mssql", + "NAME": "LibraryDB", + "USER": "django_user", # or sa + "PASSWORD": "Django@123", + "HOST": "(localdb)\MSSQLLocalDB", + "OPTIONS": { + "driver": "ODBC Driver 18 for SQL Server", + "trustServerCertificate": "yes", + }, + } +} + +REST_FRAMEWORK = { + # Accept inbound datetimes like: 2026-01-11T00:00:00.000Z, 2026-01-11T00:00:00Z, 2026-01-11T00:00:00, plus ISO-8601 + "DATETIME_INPUT_FORMATS": [ + "%Y-%m-%dT%H:%M:%S.%fZ", # 2026-01-11T00:00:00.000Z + "%Y-%m-%dT%H:%M:%SZ", # 2026-01-11T00:00:00Z + "%Y-%m-%dT%H:%M:%S", # 2026-01-11T00:00:00 + "iso-8601", # allow DRF's ISO parser (handles offsets, e.g., +05:30) + ], + # Accept inbound dates like: 2026-01-11, and also allow datetime-shaped strings to be reduced to date + "DATE_INPUT_FORMATS": [ + "%Y-%m-%d", # 2026-01-11 + "%Y-%m-%dT%H:%M:%S.%fZ", # 2026-01-11T00:00:00.000Z + "%Y-%m-%dT%H:%M:%SZ", # 2026-01-11T00:00:00Z + "%Y-%m-%dT%H:%M:%S", # 2026-01-11T00:00:00 + "iso-8601", + ], + + 'DEFAULT_PARSER_CLASSES': [ + 'rest_framework.parsers.JSONParser', + 'rest_framework.parsers.FormParser', + 'rest_framework.parsers.MultiPartParser', + ], + "DEFAULT_FILTER_BACKENDS": [ + "django_filters.rest_framework.DjangoFilterBackend", + "rest_framework.filters.SearchFilter", + "rest_framework.filters.OrderingFilter", + ], + "PAGE_SIZE_QUERY_PARAM": "page_size", + "MAX_PAGE_SIZE": 5000, +} + +ROOT_URLCONF = 'server.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'server.wsgi.application' + + +# Password validation +# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + + +USER = "django_user" +PASSWORD = "Django@123" \ No newline at end of file diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/urls.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/urls.py new file mode 100644 index 0000000..c083a2f --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/urls.py @@ -0,0 +1,29 @@ +""" +URL configuration for server project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" + +from django.contrib import admin +from django.urls import path, include +from rest_framework.routers import DefaultRouter +from library.views import BookLendingViewSet + +router = DefaultRouter() +router.register(r"lendings", BookLendingViewSet, basename="lending") + +urlpatterns = [ + path("admin/", admin.site.urls), + path("api/", include(router.urls)), +] \ No newline at end of file diff --git a/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/wsgi.py b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/wsgi.py new file mode 100644 index 0000000..b24d424 --- /dev/null +++ b/connecting-to-backends/syncfusion-react-grid-custom-binding-with-django-server/django_server/server/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for server project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings') + +application = get_wsgi_application()