django-flat-file-exporter
Reusable Django app to request, generate asynchronously, store and download flat-file exports (xlsx, csv, tsv, json, html, parquet). It builds on flat-file-renderers for the file generation and on Django's storage API for keeping the results, so files can live on disk, S3, Google Drive... whatever storage backend you configure.
What you get:
ExportedFile/ExportStakeholdermodels tracking each export: status, timings, failure cause and stack, storage key, who requested it and who else has access.BaseExportForm: declare the filters of an export as a normal Django form. Title, description (Markdown) and filter/column catalog are taken from the docstring and the form fields.BaseExportView: GET renders the form, POST validates it, registers the export and enqueues your task.BaseExportService: renders the dataset with the chosen renderer, uploads to the storage and records every step.- A ready-made UI (catalog, list with live status polling, download, trash) and Django admin.
Install
pip install "django-flat-file-exporter[all]" # [all] = xlsx + parquet renderers and Celery
Requires Python 3.10+ and Django 5.2+. Celery is optional: any object with a delay(exported_file_id, **data)
method works as the task.
Setup
# settings.py
INSTALLED_APPS = [
# ...
"django.contrib.humanize",
"flat_file_exporter",
]
# urls.py
urlpatterns = [
path("exports/", include("flat_file_exporter.urls")),
]
python manage.py migrate
Grant users the flat_file_exporter.view_exportedfile permission to let them use the pages.
Declare an export
# people/forms.py (forms are discovered in the `forms` module of every installed app)
from django import forms
from flat_file_exporter.forms import BaseExportForm, ExportColumn
class PeopleExportForm(BaseExportForm):
"""People list
All the people, optionally filtered by age. Markdown is supported here.
"""
url_name = "people:export" # URL name of the view below
columns = [ExportColumn("name", "Full name"), ExportColumn("age")]
min_age = forms.IntegerField(label="Minimum age", required=False)
# people/tasks.py
from celery import shared_task
from flat_file_exporter.models import ExportedFile
from flat_file_exporter.services import BaseExportService
class PeopleService(BaseExportService):
def get_dataset(self): # a list of dicts, a dict, or a QuerySet
return list(Person.objects.values("name", "age"))
@shared_task
def people_export(exported_file_id, filetype="csv", **filters):
PeopleService(ExportedFile.objects.get(pk=exported_file_id), filetype).render()
# people/views.py and urls.py
from flat_file_exporter.views import BaseExportView
class PeopleExportView(BaseExportView):
permission_required = "flat_file_exporter.view_exportedfile"
form_class = PeopleExportForm
task_ref = people_export
content_type_export = "application/zip"
urlpatterns = [path("export/", PeopleExportView.as_view(), name="export")] # app_name = "people"
The export now appears in the catalog at /exports/. The user picks a format in the form, the task runs in the
background, and the list page polls the status until the file can be downloaded.
Settings
| Setting | Default | Meaning |
|---|---|---|
FLAT_FILE_EXPORTER_STORAGE_ALIAS |
"default" |
Alias in STORAGES used to save the generated files |
FLAT_FILE_EXPORTER_UPLOAD_PREFIX |
"flat_file_exporter" |
Directory inside the storage |
FLAT_FILE_EXPORTER_FILETYPES |
see conf.DEFAULT_FILETYPES |
Filetype to renderer map; entries replace the defaults, None removes one |
FLAT_FILE_EXPORTER_BASE_TEMPLATE |
"flat_file_exporter/base.html" |
Layout the pages extend |
FLAT_FILE_EXPORTER_VISIBILITY |
"own" |
"own": users see only exports they are a stakeholder of; "all": every export |
The bundled base layout loads Bootstrap 4, jQuery and Font Awesome 5 from CDNs. To use your own layout (for example
AdminLTE 3), point FLAT_FILE_EXPORTER_BASE_TEMPLATE at a template that provides the blocks extra_styles,
content and bottom_scripts, with jQuery and Bootstrap 4 loaded.
Translations
All texts are translatable (gettext), with English as the source language. A pt_BR catalog is included; the
language follows Django's active language (LANGUAGE_CODE / LocaleMiddleware). The strings used by the bundled
JavaScript are delivered by the list page as window.flatFileExporterI18n.
To add a language, run django-admin makemessages -l <code> inside the flat_file_exporter directory, translate
locale/<code>/LC_MESSAGES/django.po and run django-admin compilemessages. Note that the {% trans %} tag doubles
% when looking a message up, so msgids that contain %s in the templates are %%s in the catalog.
Security notes
- Downloading and trashing an export requires being one of its stakeholders (the requester is added automatically).
- The failure stack trace is only returned by the status endpoint to superusers.
- Generated files are read through the storage API; make sure the storage you configure is not publicly readable.
Development
uv venv && uv pip install -e ".[dev]"
pytest --cov
ruff check . && ruff format --check .
License
MIT
Metadata
Release files for django-flat-file-exporter 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| django_flat_file_exporter-0.1.0.tar.gz | 39.6 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_flat_file_exporter-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 79.1 kB
Release files / django_flat_file_exporter-0.1.0.tar.gz
| Download URL | django_flat_file_exporter-0.1.0.tar.gz |
|---|---|
| Size | 39.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0e0accb6757dccba5bba8603002e5776da95e60a35c26d3ffc4ad828186bae6b
|
|
BLAKE2b-256 checksum How to use checksums |
cd7056d7a9ce3741fd685abffecb00e411bf92486c4e86442533d29670adfff2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logRelease files / django_flat_file_exporter-0.1.0-py3-none-any.whl
| Download URL | django_flat_file_exporter-0.1.0-py3-none-any.whl |
|---|---|
| Size | 39.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f1758b24b1ff9ccf734d45adff7545872ec33b4fcca316ae5cf9f94ea2f05ad7
|
|
BLAKE2b-256 checksum How to use checksums |
6d76cdb009aef0bafbae0c139d60a73e9435147d5509d16c58f2345ae5bc35a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logSecurity for django-flat-file-exporter 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for django_flat_file_exporter-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.