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.
- freehand_kit_import_export-1.0.0/.gitignore +49 -0
- freehand_kit_import_export-1.0.0/CHANGELOG.md +153 -0
- freehand_kit_import_export-1.0.0/CODE_OF_CONDUCT.md +5 -0
- freehand_kit_import_export-1.0.0/CONTRIBUTING.md +17 -0
- freehand_kit_import_export-1.0.0/LICENSE +21 -0
- freehand_kit_import_export-1.0.0/PKG-INFO +202 -0
- freehand_kit_import_export-1.0.0/README.md +159 -0
- freehand_kit_import_export-1.0.0/SECURITY.md +15 -0
- freehand_kit_import_export-1.0.0/docs/api-reference.md +75 -0
- freehand_kit_import_export-1.0.0/docs/architecture/ADR-0001-engine-and-safety-boundary.md +25 -0
- freehand_kit_import_export-1.0.0/docs/compatibility.md +5 -0
- freehand_kit_import_export-1.0.0/docs/configuration.md +128 -0
- freehand_kit_import_export-1.0.0/docs/index.md +26 -0
- freehand_kit_import_export-1.0.0/docs/installation.md +113 -0
- freehand_kit_import_export-1.0.0/docs/integration-hooks.md +38 -0
- freehand_kit_import_export-1.0.0/docs/operations.md +52 -0
- freehand_kit_import_export-1.0.0/docs/quickstart.md +276 -0
- freehand_kit_import_export-1.0.0/docs/security.md +36 -0
- freehand_kit_import_export-1.0.0/docs/testing.md +14 -0
- freehand_kit_import_export-1.0.0/examples/basic_project/README.md +5 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/.env.example +9 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/Dockerfile +20 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/README.md +114 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/accounts/__init__.py +1 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/accounts/admin.py +10 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/accounts/apps.py +6 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/accounts/migrations/0001_initial.py +114 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/accounts/migrations/__init__.py +0 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/accounts/models.py +15 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/compose.yaml +61 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/config/__init__.py +1 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/config/settings.py +115 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/config/urls.py +8 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/config/wsgi.py +6 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/inventory/__init__.py +1 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/inventory/admin.py +13 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/inventory/apps.py +6 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/inventory/migrations/0001_initial.py +88 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/inventory/migrations/__init__.py +0 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/inventory/models.py +38 -0
- freehand_kit_import_export-1.0.0/examples/production_demo/manage.py +16 -0
- freehand_kit_import_export-1.0.0/pyproject.toml +117 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/__init__.py +3 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/admin.py +46 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/api/__init__.py +1 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/api/serializers.py +88 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/api/views.py +522 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/apps.py +14 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/checks.py +12 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/conf.py +692 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/docs_urls.py +21 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/management/__init__.py +1 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/management/commands/__init__.py +1 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/management/commands/process_import_jobs.py +43 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/management/commands/purge_import_jobs.py +56 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/0001_initial.py +62 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/0002_importjob_lifecycle_timestamps.py +25 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/0003_rename_importjob_indexes.py +20 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/0004_importjob_queue_lifecycle.py +58 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/0005_importjob_source_deleted_at.py +15 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/migrations/__init__.py +1 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/models.py +59 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/policies.py +188 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/py.typed +1 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/querying.py +264 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/registry.py +125 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/services.py +688 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/signals.py +67 -0
- freehand_kit_import_export-1.0.0/src/fk_import_export/urls.py +62 -0
- freehand_kit_import_export-1.0.0/tests/__init__.py +1 -0
- freehand_kit_import_export-1.0.0/tests/central_urls.py +8 -0
- freehand_kit_import_export-1.0.0/tests/integration/test_api.py +940 -0
- freehand_kit_import_export-1.0.0/tests/settings.py +58 -0
- freehand_kit_import_export-1.0.0/tests/test_app/__init__.py +1 -0
- freehand_kit_import_export-1.0.0/tests/test_app/apps.py +7 -0
- freehand_kit_import_export-1.0.0/tests/test_app/migrations/0001_initial.py +32 -0
- freehand_kit_import_export-1.0.0/tests/test_app/migrations/0002_tag_product_tags.py +31 -0
- freehand_kit_import_export-1.0.0/tests/test_app/migrations/0003_product_owner.py +24 -0
- freehand_kit_import_export-1.0.0/tests/test_app/migrations/__init__.py +1 -0
- freehand_kit_import_export-1.0.0/tests/test_app/models.py +36 -0
- freehand_kit_import_export-1.0.0/tests/test_app/policies.py +28 -0
- freehand_kit_import_export-1.0.0/tests/unit/test_admin.py +13 -0
- freehand_kit_import_export-1.0.0/tests/unit/test_checks.py +5 -0
- freehand_kit_import_export-1.0.0/tests/unit/test_configuration.py +181 -0
- 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,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.
|