freehand-kit-import-export 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. freehand_kit_import_export-1.0.0/.gitignore +49 -0
  2. freehand_kit_import_export-1.0.0/CHANGELOG.md +153 -0
  3. freehand_kit_import_export-1.0.0/CODE_OF_CONDUCT.md +5 -0
  4. freehand_kit_import_export-1.0.0/CONTRIBUTING.md +17 -0
  5. freehand_kit_import_export-1.0.0/LICENSE +21 -0
  6. freehand_kit_import_export-1.0.0/PKG-INFO +202 -0
  7. freehand_kit_import_export-1.0.0/README.md +159 -0
  8. freehand_kit_import_export-1.0.0/SECURITY.md +15 -0
  9. freehand_kit_import_export-1.0.0/docs/api-reference.md +75 -0
  10. freehand_kit_import_export-1.0.0/docs/architecture/ADR-0001-engine-and-safety-boundary.md +25 -0
  11. freehand_kit_import_export-1.0.0/docs/compatibility.md +5 -0
  12. freehand_kit_import_export-1.0.0/docs/configuration.md +128 -0
  13. freehand_kit_import_export-1.0.0/docs/index.md +26 -0
  14. freehand_kit_import_export-1.0.0/docs/installation.md +113 -0
  15. freehand_kit_import_export-1.0.0/docs/integration-hooks.md +38 -0
  16. freehand_kit_import_export-1.0.0/docs/operations.md +52 -0
  17. freehand_kit_import_export-1.0.0/docs/quickstart.md +276 -0
  18. freehand_kit_import_export-1.0.0/docs/security.md +36 -0
  19. freehand_kit_import_export-1.0.0/docs/testing.md +14 -0
  20. freehand_kit_import_export-1.0.0/examples/basic_project/README.md +5 -0
  21. freehand_kit_import_export-1.0.0/examples/production_demo/.env.example +9 -0
  22. freehand_kit_import_export-1.0.0/examples/production_demo/Dockerfile +20 -0
  23. freehand_kit_import_export-1.0.0/examples/production_demo/README.md +114 -0
  24. freehand_kit_import_export-1.0.0/examples/production_demo/accounts/__init__.py +1 -0
  25. freehand_kit_import_export-1.0.0/examples/production_demo/accounts/admin.py +10 -0
  26. freehand_kit_import_export-1.0.0/examples/production_demo/accounts/apps.py +6 -0
  27. freehand_kit_import_export-1.0.0/examples/production_demo/accounts/migrations/0001_initial.py +114 -0
  28. freehand_kit_import_export-1.0.0/examples/production_demo/accounts/migrations/__init__.py +0 -0
  29. freehand_kit_import_export-1.0.0/examples/production_demo/accounts/models.py +15 -0
  30. freehand_kit_import_export-1.0.0/examples/production_demo/compose.yaml +61 -0
  31. freehand_kit_import_export-1.0.0/examples/production_demo/config/__init__.py +1 -0
  32. freehand_kit_import_export-1.0.0/examples/production_demo/config/settings.py +115 -0
  33. freehand_kit_import_export-1.0.0/examples/production_demo/config/urls.py +8 -0
  34. freehand_kit_import_export-1.0.0/examples/production_demo/config/wsgi.py +6 -0
  35. freehand_kit_import_export-1.0.0/examples/production_demo/inventory/__init__.py +1 -0
  36. freehand_kit_import_export-1.0.0/examples/production_demo/inventory/admin.py +13 -0
  37. freehand_kit_import_export-1.0.0/examples/production_demo/inventory/apps.py +6 -0
  38. freehand_kit_import_export-1.0.0/examples/production_demo/inventory/migrations/0001_initial.py +88 -0
  39. freehand_kit_import_export-1.0.0/examples/production_demo/inventory/migrations/__init__.py +0 -0
  40. freehand_kit_import_export-1.0.0/examples/production_demo/inventory/models.py +38 -0
  41. freehand_kit_import_export-1.0.0/examples/production_demo/manage.py +16 -0
  42. freehand_kit_import_export-1.0.0/pyproject.toml +117 -0
  43. freehand_kit_import_export-1.0.0/src/fk_import_export/__init__.py +3 -0
  44. freehand_kit_import_export-1.0.0/src/fk_import_export/admin.py +46 -0
  45. freehand_kit_import_export-1.0.0/src/fk_import_export/api/__init__.py +1 -0
  46. freehand_kit_import_export-1.0.0/src/fk_import_export/api/serializers.py +88 -0
  47. freehand_kit_import_export-1.0.0/src/fk_import_export/api/views.py +522 -0
  48. freehand_kit_import_export-1.0.0/src/fk_import_export/apps.py +14 -0
  49. freehand_kit_import_export-1.0.0/src/fk_import_export/checks.py +12 -0
  50. freehand_kit_import_export-1.0.0/src/fk_import_export/conf.py +692 -0
  51. freehand_kit_import_export-1.0.0/src/fk_import_export/docs_urls.py +21 -0
  52. freehand_kit_import_export-1.0.0/src/fk_import_export/management/__init__.py +1 -0
  53. freehand_kit_import_export-1.0.0/src/fk_import_export/management/commands/__init__.py +1 -0
  54. freehand_kit_import_export-1.0.0/src/fk_import_export/management/commands/process_import_jobs.py +43 -0
  55. freehand_kit_import_export-1.0.0/src/fk_import_export/management/commands/purge_import_jobs.py +56 -0
  56. freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/0001_initial.py +62 -0
  57. freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/0002_importjob_lifecycle_timestamps.py +25 -0
  58. freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/0003_rename_importjob_indexes.py +20 -0
  59. freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/0004_importjob_queue_lifecycle.py +58 -0
  60. freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/0005_importjob_source_deleted_at.py +15 -0
  61. freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/__init__.py +1 -0
  62. freehand_kit_import_export-1.0.0/src/fk_import_export/models.py +59 -0
  63. freehand_kit_import_export-1.0.0/src/fk_import_export/policies.py +188 -0
  64. freehand_kit_import_export-1.0.0/src/fk_import_export/py.typed +1 -0
  65. freehand_kit_import_export-1.0.0/src/fk_import_export/querying.py +264 -0
  66. freehand_kit_import_export-1.0.0/src/fk_import_export/registry.py +125 -0
  67. freehand_kit_import_export-1.0.0/src/fk_import_export/services.py +688 -0
  68. freehand_kit_import_export-1.0.0/src/fk_import_export/signals.py +67 -0
  69. freehand_kit_import_export-1.0.0/src/fk_import_export/urls.py +62 -0
  70. freehand_kit_import_export-1.0.0/tests/__init__.py +1 -0
  71. freehand_kit_import_export-1.0.0/tests/central_urls.py +8 -0
  72. freehand_kit_import_export-1.0.0/tests/integration/test_api.py +940 -0
  73. freehand_kit_import_export-1.0.0/tests/settings.py +58 -0
  74. freehand_kit_import_export-1.0.0/tests/test_app/__init__.py +1 -0
  75. freehand_kit_import_export-1.0.0/tests/test_app/apps.py +7 -0
  76. freehand_kit_import_export-1.0.0/tests/test_app/migrations/0001_initial.py +32 -0
  77. freehand_kit_import_export-1.0.0/tests/test_app/migrations/0002_tag_product_tags.py +31 -0
  78. freehand_kit_import_export-1.0.0/tests/test_app/migrations/0003_product_owner.py +24 -0
  79. freehand_kit_import_export-1.0.0/tests/test_app/migrations/__init__.py +1 -0
  80. freehand_kit_import_export-1.0.0/tests/test_app/models.py +36 -0
  81. freehand_kit_import_export-1.0.0/tests/test_app/policies.py +28 -0
  82. freehand_kit_import_export-1.0.0/tests/unit/test_admin.py +13 -0
  83. freehand_kit_import_export-1.0.0/tests/unit/test_checks.py +5 -0
  84. freehand_kit_import_export-1.0.0/tests/unit/test_configuration.py +181 -0
  85. freehand_kit_import_export-1.0.0/tests/unit/test_registry.py +59 -0
@@ -0,0 +1,49 @@
1
+ # Python bytecode and environments
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ .venv/
6
+ venv/
7
+ env/
8
+ .tox/
9
+ .nox/
10
+
11
+ # Test, type-check, and coverage output
12
+ .mypy_cache/
13
+ .pytest_cache/
14
+ .ruff_cache/
15
+ .coverage
16
+ .coverage.*
17
+ htmlcov/
18
+ coverage.xml
19
+
20
+ # Packaging artifacts
21
+ build/
22
+ dist/
23
+ *.egg-info/
24
+ *.egg
25
+ *.whl
26
+ pip-wheel-metadata/
27
+
28
+ # Django runtime state
29
+ *.sqlite3
30
+ *.sqlite3-journal
31
+ media/
32
+ tests/.test-media/
33
+ examples/production_demo/private-media/
34
+ staticfiles/
35
+ *.log
36
+
37
+ # Local configuration: retain examples, never credentials
38
+ .env
39
+ .env.*
40
+ !.env.example
41
+ !.env.*.example
42
+
43
+ # Editors and operating-system files
44
+ .idea/
45
+ .vscode/
46
+ *.code-workspace
47
+ .DS_Store
48
+ Thumbs.db
49
+ Desktop.ini
@@ -0,0 +1,153 @@
1
+ # Changelog
2
+
3
+ All notable changes to this package are documented here. The project follows
4
+ [Semantic Versioning](https://semver.org/).
5
+
6
+ ## [1.0.0] - 2026-10-06
7
+
8
+ ### Changed
9
+
10
+ - Promoted the tested CSV-first import/export API, durable worker workflow, documented
11
+ OpenAPI routes, and production consumer demo to the first stable release.
12
+ - Declared the package as `Production/Stable` in its distribution metadata. The supported
13
+ compatibility range remains Python 3.11–3.13 and Django 5.2–6.0.
14
+ - Reworked public documentation around an end-to-end quickstart, explicit CSV-only support,
15
+ practical installation steps, and a clearer API workflow.
16
+
17
+ ## [0.10.0] - 2026-10-03
18
+
19
+ ### Added
20
+
21
+ - Optional central OpenAPI routes for the shared Freehand Kit convention:
22
+ `/api/schema/` and `/api/docs/`. They document import/export endpoints alongside
23
+ every other host DRF API without moving resource endpoints from `/api/data/`.
24
+
25
+ ## [0.9.2] - 2026-10-03
26
+
27
+ ### Changed
28
+
29
+ - The Docker consumer demo runs migrations in one short-lived service. Web and worker
30
+ now wait for that migration to complete successfully, preventing concurrent startup
31
+ migration attempts.
32
+
33
+ ## [0.9.1] - 2026-10-03
34
+
35
+ ### Fixed
36
+
37
+ - Apply server-controlled owner/tenant scopes before model validation, so a scoped
38
+ resource whose model requires that field can successfully complete preview and import.
39
+ - Exclude local SQLite state and private demonstration upload storage from Docker build
40
+ contexts.
41
+
42
+ ### Added
43
+
44
+ - A Dockerized custom-user consumer demo with PostgreSQL, a separate import worker,
45
+ private storage, relational data, and an end-to-end operator guide.
46
+
47
+ ## [0.9.0] - 2026-10-03
48
+
49
+ ### Added
50
+
51
+ - Owner-private, import-permission-filtered `GET import-jobs/` history with bounded
52
+ pagination and resource/status filters.
53
+
54
+ ## [0.8.0] - 2026-10-03
55
+
56
+ ### Added
57
+
58
+ - Optional, typed host `ResourcePolicy` classes for indirect tenancy, memberships, and
59
+ other domain-specific queryset and import-instance rules.
60
+
61
+ ### Security
62
+
63
+ - Policy classes must be an explicitly configured, zero-argument subclass of the public
64
+ `ResourcePolicy` base class. They compose with—not replace—resource permissions,
65
+ field allowlists, and direct scopes.
66
+
67
+ ## [0.7.0] - 2026-10-03
68
+
69
+ ### Added
70
+
71
+ - Transaction-safe Django lifecycle signals for previewed, queued, committed, and failed
72
+ import jobs.
73
+
74
+ ### Changed
75
+
76
+ - Corrected the package runtime version to match distribution metadata.
77
+
78
+ ## [0.6.0] - 2026-10-03
79
+
80
+ ### Added
81
+
82
+ - Opt-in retention settings and a bounded `purge_import_jobs` management command.
83
+ - Source-deletion audit timestamps on retained terminal import-job records.
84
+
85
+ ### Security
86
+
87
+ - Retention processing considers only committed and failed jobs, defaults to dry-run,
88
+ and requires `--apply` before any source object or job record is removed.
89
+
90
+ ## [0.5.0] - 2026-10-03
91
+
92
+ ### Added
93
+
94
+ - Per-resource Django permission policies for read, export, and import operations.
95
+ - Direct owner/tenant scope configuration applied to records, exports, import matching,
96
+ and worker commits.
97
+
98
+ ### Security
99
+
100
+ - Resource discovery now returns only resources whose declared read policy permits the
101
+ caller. Scoped imports attach the declared owner/tenant value server-side.
102
+
103
+ ## [0.4.0] - 2026-10-02
104
+
105
+ ### Added
106
+
107
+ - Durable database-backed import queue states, attempts, timestamps, and progress counters.
108
+ - Bundled `process_import_jobs` Django management command with stale-job recovery and a
109
+ bounded retry budget.
110
+ - Owner-scoped, sanitized CSV error-report download endpoint.
111
+
112
+ ### Changed
113
+
114
+ - Confirmation now returns `202 Accepted` after queuing a successful preview; a worker
115
+ atomically commits the import and records terminal state.
116
+
117
+ ## [0.3.0] - 2026-10-02
118
+
119
+ ### Added
120
+
121
+ - Paginated configured-record APIs and bounded CSV export APIs.
122
+ - Allowlisted search, ordering, exact filtering, relationship lookup filtering, and
123
+ spreadsheet-formula-safe CSV cell serialization.
124
+ - Explicit relation requirements and validation that disallows many-to-many ordering.
125
+
126
+ ## [0.2.0] - 2026-10-02
127
+
128
+ ### Added
129
+
130
+ - CSV preview, owner-scoped import-job detail, and explicit confirmation endpoints.
131
+ - Bounded UTF-8 CSV validation, exact header contracts, row and upload-size limits,
132
+ stored-source hashing, dry-run preview, atomic confirmation, and retry-safe commits.
133
+ - Lifecycle timestamps and sanitized, capped import error summaries.
134
+
135
+ ### Security
136
+
137
+ - Previewed jobs are private to the submitting staff user; an unknown or foreign job
138
+ returns `404`.
139
+ - Confirmation rechecks the stored source hash and CSV contract before mutation.
140
+
141
+ ## [0.1.0] - 2026-10-02
142
+
143
+ ### Added
144
+
145
+ - Independent package foundation for declarative Django model import/export.
146
+ - Namespaced resource registry, Django system checks, `django-import-export` engine
147
+ boundary, import-job audit model, and Swagger-ready discovery/template APIs.
148
+ - CSV-first safety and relationship configuration contract.
149
+
150
+ ### Security
151
+
152
+ - Explicit resource and field allowlists; denylist for Django credential and privilege
153
+ fields; declared import identifiers; and no automatic related-object creation.
@@ -0,0 +1,5 @@
1
+ # Code of Conduct
2
+
3
+ Be respectful, constructive, and professional. Harassment, discrimination, and
4
+ publication of private or sensitive data are not acceptable. Report concerns privately
5
+ to the repository maintainer.
@@ -0,0 +1,17 @@
1
+ # Contributing
2
+
3
+ Use a feature branch and pull request. Keep data-mutation changes accompanied by
4
+ negative tests, migration review, and API-schema coverage.
5
+
6
+ Before opening a pull request, run:
7
+
8
+ ```bash
9
+ python -m pytest
10
+ ruff format --check src tests
11
+ ruff check src tests
12
+ mypy src
13
+ python -m build
14
+ twine check dist/*
15
+ ```
16
+
17
+ Never commit production datasets, uploaded files, API tokens, or `.env` files.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Freehand Kit contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,202 @@
1
+ Metadata-Version: 2.5
2
+ Name: freehand-kit-import-export
3
+ Version: 1.0.0
4
+ Summary: Declarative, CSV-first Django REST Framework import and export APIs.
5
+ Project-URL: Documentation, https://github.com/anser14/free-hand-kit-import-export#readme
6
+ Project-URL: Issues, https://github.com/anser14/free-hand-kit-import-export/issues
7
+ Project-URL: Source, https://github.com/anser14/free-hand-kit-import-export
8
+ Project-URL: Changelog, https://github.com/anser14/free-hand-kit-import-export/blob/main/CHANGELOG.md
9
+ Project-URL: Security, https://github.com/anser14/free-hand-kit-import-export/security/policy
10
+ Author: Freehand Kit contributors
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: csv,django,django-rest-framework,export,import,openapi
14
+ Classifier: Development Status :: 5 - Production/Stable
15
+ Classifier: Framework :: Django
16
+ Classifier: Framework :: Django :: 5.2
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Internet :: WWW/HTTP
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.11
27
+ Requires-Dist: django-import-export<5,>=4.4
28
+ Requires-Dist: django<6.1,>=5.2
29
+ Requires-Dist: djangorestframework<3.18,>=3.17.2
30
+ Requires-Dist: drf-spectacular<1,>=0.29
31
+ Provides-Extra: dev
32
+ Requires-Dist: build>=1.2; extra == 'dev'
33
+ Requires-Dist: coverage[toml]>=7.6; extra == 'dev'
34
+ Requires-Dist: django-stubs[compatible-mypy]>=5.1; extra == 'dev'
35
+ Requires-Dist: djangorestframework-stubs>=3.15; extra == 'dev'
36
+ Requires-Dist: mypy>=1.13; extra == 'dev'
37
+ Requires-Dist: pytest-django>=4.9; extra == 'dev'
38
+ Requires-Dist: pytest>=8.3; extra == 'dev'
39
+ Requires-Dist: ruff>=0.8; extra == 'dev'
40
+ Requires-Dist: twine>=6.0; extra == 'dev'
41
+ Requires-Dist: types-django-import-export<5,>=4.4.0.20260402; extra == 'dev'
42
+ Description-Content-Type: text/markdown
43
+
44
+ # Freehand Kit Import Export: Django REST Framework CSV Import/Export API
45
+
46
+ `freehand-kit-import-export` gives Django and Django REST Framework projects a secure,
47
+ configuration-first API for importing and exporting model data as CSV. Register an
48
+ approved model once in Django settings; the package provides discoverable endpoints,
49
+ Swagger/OpenAPI documentation, CSV templates, dry-run validation, a durable import queue,
50
+ and bounded exports.
51
+
52
+ > **Status: stable.** Version `1.0.0` is the first stable release. It supports Python
53
+ > 3.11–3.13, Django 5.2–6.0, and Django REST Framework 3.17.x.
54
+
55
+ ## Why use this Django import/export package?
56
+
57
+ Most Django projects need CSV import and export sooner or later: product catalog uploads,
58
+ member updates, back-office data fixes, onboarding data, or customer reports. Rebuilding
59
+ serializers, CSV parsing, validation, permission checks, pagination, and API documentation
60
+ for every model is repetitive and easy to get wrong.
61
+
62
+ Freehand Kit Import Export lets the host application keep control of its models and access
63
+ rules while the package owns the reusable workflow. API callers can use only resources and
64
+ fields that the host developer explicitly approves; they cannot submit arbitrary model names
65
+ or field lists.
66
+
67
+ | You configure | The package provides |
68
+ | --- | --- |
69
+ | Django model, permitted fields, identifiers, relations, permissions, and optional owner/tenant scope | Resource discovery, CSV template, preview, confirmation, job history, records, and export APIs |
70
+ | Authentication in your project | Permission checks on every endpoint; the package never creates an authentication system |
71
+ | A worker or scheduler | Durable, retry-bounded import processing after an explicit confirmation |
72
+ | Private storage and retention policy | Source hashes, sanitized error reports, and safe cleanup commands |
73
+
74
+ ## Supported workflow
75
+
76
+ 1. A developer registers a model as a named resource, for example `products`.
77
+ 2. An authorized user downloads the exact CSV template or creates a matching UTF-8 CSV.
78
+ 3. The user uploads it to the **preview** endpoint. No model rows are written yet.
79
+ 4. The API returns a job with validation results. The user confirms only a successful preview.
80
+ 5. A background worker revalidates the saved file and atomically writes the model rows.
81
+ 6. The user polls the job, downloads sanitized errors when needed, lists records, or exports CSV.
82
+
83
+ Imports are CSV-only in `1.0.0`. XLSX, JSON, and arbitrary model/field submission are not
84
+ supported by this package version.
85
+
86
+ ## Install and run your first import
87
+
88
+ ```bash
89
+ python -m pip install freehand-kit-import-export
90
+ ```
91
+
92
+ 1. Add `rest_framework`, `drf_spectacular`, and `fk_import_export` to `INSTALLED_APPS`.
93
+ 2. Register a resource in `FREEHAND_KIT_IMPORT_EXPORT`.
94
+ 3. Mount `/api/data/` and the shared Swagger route at `/api/docs/`.
95
+ 4. Run `python manage.py migrate` and `python manage.py check --tag fk_import_export`.
96
+ 5. Run `python manage.py process_import_jobs --max-jobs 10` under a worker or scheduler.
97
+
98
+ The complete copy-and-paste tutorial—including settings, URLs, CSV upload, preview,
99
+ confirmation, worker processing, records, exports, errors, and production checklist—is in
100
+ [the quickstart guide](docs/quickstart.md).
101
+
102
+ ## Minimal Django configuration
103
+
104
+ ```python
105
+ # settings.py
106
+ INSTALLED_APPS = [
107
+ # Your Django apps...
108
+ "rest_framework",
109
+ "drf_spectacular",
110
+ "fk_import_export",
111
+ ]
112
+
113
+ REST_FRAMEWORK = {
114
+ "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
115
+ }
116
+
117
+ FREEHAND_KIT_IMPORT_EXPORT = {
118
+ "RESOURCES": {
119
+ "products": {
120
+ "MODEL": "inventory.Product",
121
+ "IMPORT_FIELDS": ("sku", "name", "price"),
122
+ "EXPORT_FIELDS": ("sku", "name", "price"),
123
+ "IMPORT_ID_FIELDS": ("sku",),
124
+ "SEARCH_FIELDS": ("sku", "name"),
125
+ "ORDERING_FIELDS": ("sku", "name", "price"),
126
+ "FILTER_FIELDS": (),
127
+ "PERMISSIONS": {
128
+ "READ": "inventory.view_product",
129
+ "EXPORT": "inventory.view_product",
130
+ "IMPORT": "inventory.change_product",
131
+ },
132
+ },
133
+ },
134
+ }
135
+ ```
136
+
137
+ ```python
138
+ # urls.py
139
+ from django.urls import include, path
140
+
141
+ urlpatterns = [
142
+ path("api/data/", include("fk_import_export.urls")),
143
+ path("api/", include("fk_import_export.docs_urls")),
144
+ ]
145
+ ```
146
+
147
+ Visit `/api/docs/` after starting the Django project. If your project already exposes a
148
+ central drf-spectacular schema—such as one mounted by `fk_auth`—do **not** mount
149
+ `fk_import_export.docs_urls` again. The existing `/api/docs/` automatically includes these
150
+ endpoints.
151
+
152
+ ## Core features
153
+
154
+ - **Plug-and-play Django REST Framework endpoints** for approved Django models.
155
+ - **CSV import preview and confirmation** so invalid data is never written accidentally.
156
+ - **Durable worker queue** with retries, stale-job recovery, atomic commits, and job history.
157
+ - **Secure relation handling** with explicit unique lookups; related rows are never silently created.
158
+ - **Per-resource Django permissions** and direct owner/tenant scopes.
159
+ - **Paginated records API** with allowlisted search, ordering, and filters.
160
+ - **Bounded CSV exports** with spreadsheet formula-injection protection.
161
+ - **Automatic Swagger/OpenAPI documentation** at `/api/docs/` and `/api/schema/`.
162
+ - **Sanitized error reports, lifecycle signals, and retention tools** for operating imports safely.
163
+
164
+ ## Common use cases
165
+
166
+ - Django admin or operations teams importing product, inventory, pricing, customer, or membership CSV files.
167
+ - React, Vue, mobile, and partner clients using a documented Django REST Framework import API.
168
+ - SaaS applications that must isolate data by owner or tenant during import and export.
169
+ - Back-office systems that need searchable JSON records alongside downloadable CSV reports.
170
+
171
+ ## Security model
172
+
173
+ The package is intentionally restrictive:
174
+
175
+ - Only registered resources and explicit fields are exposed.
176
+ - Sensitive fields—passwords, staff flags, groups, permissions, and tokens—are denied by default.
177
+ - Uploads must be UTF-8 `.csv` files with exact headers and configured byte/row limits.
178
+ - Preview and worker execution are transactional; confirming a job is safe to retry.
179
+ - Stored errors contain line numbers and categories, never uploaded cell values or raw database exceptions.
180
+ - CSV exports are capped and guarded against spreadsheet formula injection.
181
+
182
+ You must still configure your application's authentication, private media storage,
183
+ permissions, tenant rules, backups, and monitoring. Read the [security guide](docs/security.md)
184
+ before accepting real customer data.
185
+
186
+ ## Documentation
187
+
188
+ - **Start here:** [end-to-end quickstart](docs/quickstart.md)
189
+ - [Installation and URL setup](docs/installation.md)
190
+ - [Resource configuration reference](docs/configuration.md)
191
+ - [API endpoint reference](docs/api-reference.md)
192
+ - [Worker, retries, and retention operations](docs/operations.md)
193
+ - [Custom authorization policies](docs/configuration.md#custom-resource-policy)
194
+ - [Lifecycle integration hooks](docs/integration-hooks.md)
195
+ - [Production-style Docker demo with a custom user model](examples/production_demo/README.md)
196
+ - [Security guidance](docs/security.md)
197
+ - [Compatibility and supported versions](docs/compatibility.md)
198
+ - [Architecture decision](docs/architecture/ADR-0001-engine-and-safety-boundary.md)
199
+
200
+ ## License
201
+
202
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,159 @@
1
+ # Freehand Kit Import Export: Django REST Framework CSV Import/Export API
2
+
3
+ `freehand-kit-import-export` gives Django and Django REST Framework projects a secure,
4
+ configuration-first API for importing and exporting model data as CSV. Register an
5
+ approved model once in Django settings; the package provides discoverable endpoints,
6
+ Swagger/OpenAPI documentation, CSV templates, dry-run validation, a durable import queue,
7
+ and bounded exports.
8
+
9
+ > **Status: stable.** Version `1.0.0` is the first stable release. It supports Python
10
+ > 3.11–3.13, Django 5.2–6.0, and Django REST Framework 3.17.x.
11
+
12
+ ## Why use this Django import/export package?
13
+
14
+ Most Django projects need CSV import and export sooner or later: product catalog uploads,
15
+ member updates, back-office data fixes, onboarding data, or customer reports. Rebuilding
16
+ serializers, CSV parsing, validation, permission checks, pagination, and API documentation
17
+ for every model is repetitive and easy to get wrong.
18
+
19
+ Freehand Kit Import Export lets the host application keep control of its models and access
20
+ rules while the package owns the reusable workflow. API callers can use only resources and
21
+ fields that the host developer explicitly approves; they cannot submit arbitrary model names
22
+ or field lists.
23
+
24
+ | You configure | The package provides |
25
+ | --- | --- |
26
+ | Django model, permitted fields, identifiers, relations, permissions, and optional owner/tenant scope | Resource discovery, CSV template, preview, confirmation, job history, records, and export APIs |
27
+ | Authentication in your project | Permission checks on every endpoint; the package never creates an authentication system |
28
+ | A worker or scheduler | Durable, retry-bounded import processing after an explicit confirmation |
29
+ | Private storage and retention policy | Source hashes, sanitized error reports, and safe cleanup commands |
30
+
31
+ ## Supported workflow
32
+
33
+ 1. A developer registers a model as a named resource, for example `products`.
34
+ 2. An authorized user downloads the exact CSV template or creates a matching UTF-8 CSV.
35
+ 3. The user uploads it to the **preview** endpoint. No model rows are written yet.
36
+ 4. The API returns a job with validation results. The user confirms only a successful preview.
37
+ 5. A background worker revalidates the saved file and atomically writes the model rows.
38
+ 6. The user polls the job, downloads sanitized errors when needed, lists records, or exports CSV.
39
+
40
+ Imports are CSV-only in `1.0.0`. XLSX, JSON, and arbitrary model/field submission are not
41
+ supported by this package version.
42
+
43
+ ## Install and run your first import
44
+
45
+ ```bash
46
+ python -m pip install freehand-kit-import-export
47
+ ```
48
+
49
+ 1. Add `rest_framework`, `drf_spectacular`, and `fk_import_export` to `INSTALLED_APPS`.
50
+ 2. Register a resource in `FREEHAND_KIT_IMPORT_EXPORT`.
51
+ 3. Mount `/api/data/` and the shared Swagger route at `/api/docs/`.
52
+ 4. Run `python manage.py migrate` and `python manage.py check --tag fk_import_export`.
53
+ 5. Run `python manage.py process_import_jobs --max-jobs 10` under a worker or scheduler.
54
+
55
+ The complete copy-and-paste tutorial—including settings, URLs, CSV upload, preview,
56
+ confirmation, worker processing, records, exports, errors, and production checklist—is in
57
+ [the quickstart guide](docs/quickstart.md).
58
+
59
+ ## Minimal Django configuration
60
+
61
+ ```python
62
+ # settings.py
63
+ INSTALLED_APPS = [
64
+ # Your Django apps...
65
+ "rest_framework",
66
+ "drf_spectacular",
67
+ "fk_import_export",
68
+ ]
69
+
70
+ REST_FRAMEWORK = {
71
+ "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
72
+ }
73
+
74
+ FREEHAND_KIT_IMPORT_EXPORT = {
75
+ "RESOURCES": {
76
+ "products": {
77
+ "MODEL": "inventory.Product",
78
+ "IMPORT_FIELDS": ("sku", "name", "price"),
79
+ "EXPORT_FIELDS": ("sku", "name", "price"),
80
+ "IMPORT_ID_FIELDS": ("sku",),
81
+ "SEARCH_FIELDS": ("sku", "name"),
82
+ "ORDERING_FIELDS": ("sku", "name", "price"),
83
+ "FILTER_FIELDS": (),
84
+ "PERMISSIONS": {
85
+ "READ": "inventory.view_product",
86
+ "EXPORT": "inventory.view_product",
87
+ "IMPORT": "inventory.change_product",
88
+ },
89
+ },
90
+ },
91
+ }
92
+ ```
93
+
94
+ ```python
95
+ # urls.py
96
+ from django.urls import include, path
97
+
98
+ urlpatterns = [
99
+ path("api/data/", include("fk_import_export.urls")),
100
+ path("api/", include("fk_import_export.docs_urls")),
101
+ ]
102
+ ```
103
+
104
+ Visit `/api/docs/` after starting the Django project. If your project already exposes a
105
+ central drf-spectacular schema—such as one mounted by `fk_auth`—do **not** mount
106
+ `fk_import_export.docs_urls` again. The existing `/api/docs/` automatically includes these
107
+ endpoints.
108
+
109
+ ## Core features
110
+
111
+ - **Plug-and-play Django REST Framework endpoints** for approved Django models.
112
+ - **CSV import preview and confirmation** so invalid data is never written accidentally.
113
+ - **Durable worker queue** with retries, stale-job recovery, atomic commits, and job history.
114
+ - **Secure relation handling** with explicit unique lookups; related rows are never silently created.
115
+ - **Per-resource Django permissions** and direct owner/tenant scopes.
116
+ - **Paginated records API** with allowlisted search, ordering, and filters.
117
+ - **Bounded CSV exports** with spreadsheet formula-injection protection.
118
+ - **Automatic Swagger/OpenAPI documentation** at `/api/docs/` and `/api/schema/`.
119
+ - **Sanitized error reports, lifecycle signals, and retention tools** for operating imports safely.
120
+
121
+ ## Common use cases
122
+
123
+ - Django admin or operations teams importing product, inventory, pricing, customer, or membership CSV files.
124
+ - React, Vue, mobile, and partner clients using a documented Django REST Framework import API.
125
+ - SaaS applications that must isolate data by owner or tenant during import and export.
126
+ - Back-office systems that need searchable JSON records alongside downloadable CSV reports.
127
+
128
+ ## Security model
129
+
130
+ The package is intentionally restrictive:
131
+
132
+ - Only registered resources and explicit fields are exposed.
133
+ - Sensitive fields—passwords, staff flags, groups, permissions, and tokens—are denied by default.
134
+ - Uploads must be UTF-8 `.csv` files with exact headers and configured byte/row limits.
135
+ - Preview and worker execution are transactional; confirming a job is safe to retry.
136
+ - Stored errors contain line numbers and categories, never uploaded cell values or raw database exceptions.
137
+ - CSV exports are capped and guarded against spreadsheet formula injection.
138
+
139
+ You must still configure your application's authentication, private media storage,
140
+ permissions, tenant rules, backups, and monitoring. Read the [security guide](docs/security.md)
141
+ before accepting real customer data.
142
+
143
+ ## Documentation
144
+
145
+ - **Start here:** [end-to-end quickstart](docs/quickstart.md)
146
+ - [Installation and URL setup](docs/installation.md)
147
+ - [Resource configuration reference](docs/configuration.md)
148
+ - [API endpoint reference](docs/api-reference.md)
149
+ - [Worker, retries, and retention operations](docs/operations.md)
150
+ - [Custom authorization policies](docs/configuration.md#custom-resource-policy)
151
+ - [Lifecycle integration hooks](docs/integration-hooks.md)
152
+ - [Production-style Docker demo with a custom user model](examples/production_demo/README.md)
153
+ - [Security guidance](docs/security.md)
154
+ - [Compatibility and supported versions](docs/compatibility.md)
155
+ - [Architecture decision](docs/architecture/ADR-0001-engine-and-safety-boundary.md)
156
+
157
+ ## License
158
+
159
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,15 @@
1
+ # Security policy
2
+
3
+ ## Supported versions
4
+
5
+ Only the latest published release line receives security fixes. The package is not
6
+ production-ready until a stable 1.x release is explicitly published.
7
+
8
+ ## Reporting a vulnerability
9
+
10
+ Use GitHub private vulnerability reporting for this repository. Do not publish a
11
+ security-sensitive issue, uploaded dataset, credential, or exploit proof publicly.
12
+
13
+ For local-development reports where private reporting is unavailable, contact the
14
+ repository maintainer privately and include affected version, reproduction steps, and
15
+ impact without attaching real production data.