Skip to main content

FairDM

Tests Build Publish Documentation Coverage PyPI Development status Python Django Ruff Licence

A Django framework for building FAIR research data portals with minimal code.

FairDM makes it trivial for research teams to define domain-specific sample and measurement models and run a fully functional data portal without writing views, URL routing, or frontend code.


🎯 What is FairDM?

FairDM is an opinionated Django framework (not a library) designed specifically for research data management. It enables researchers with basic Python skills to:

  • Define custom domain models for samples and measurements
  • Get a fully functional web portal without writing views or templates
  • Ensure data follows FAIR principles (Findable, Accessible, Interoperable, Reusable)
  • Manage research projects, datasets, and contributors out of the box
  • Import/export data in multiple formats with zero configuration
  • Control access with fine-grained object-level permissions

Scope & philosophy

What FairDM is

A batteries-included Django framework for building research data portals. You describe your samples and measurements as Django models, register them, and get the portal without writing that layer yourself: views, URLs, forms, filters, tables, admin and API.

What FairDM is deliberately not

  • Not a library of parts. It is opinionated and owns the application shell. If you want to assemble your own stack from independent components, this is the wrong starting point.
  • Not a generic CMS. The core model (projects, datasets, samples, measurements and contributors) is fixed, because it is what makes portals interoperable and citable.
  • Not a single portal. Domain-specific schemas belong in portals that build on FairDM, not in the framework itself.
  • Not a JavaScript application. The server-rendered baseline is the product, not a fallback.
  • Not a formal publisher. Publishing a dataset in FairDM makes it visible to other users of the portal. Sending metadata to a data publisher and receiving a DOI in return is a separate act, and it belongs to an addon rather than the core.
  • Not the home of every feature. The core stays small and the framework grows through addons. A capability that only some portals need is an addon, not a core concern.

When principles collide

  • Configuration over code — declarative model registration with sensible defaults.
  • Domain-first modelling — accurate scientific representation outranks framework convenience.
  • Progressive complexity — registering a model works on its own. Custom forms, filters and views come later, and only for the portals that need them.
  • No frontend knowledge required — a working portal must not depend on template or JS skills.
  • FAIR by design — metadata, stable identifiers and machine access are built in, not added on.
  • A stable backbone beats a fast one — research portals outlive their funding, so the core model changes slowly and deliberately.

Where the framework is headed is a separate question from what it is. That lives in GOALS.md.


Requirements

  • Python 3.13 or later.
  • Django 6.0.

🚀 Quick Start

Prerequisites

  • Python 3.13+
  • uv for dependency management
  • PostgreSQL (recommended) or SQLite for development

Installation

# Clone the repository
git clone https://github.com/FAIR-DM/fairdm.git
cd fairdm

# Install dependencies with uv
uv sync

# Activate the virtual environment
source .venv/bin/activate

# Run database migrations
uv run python manage.py migrate

# Create a superuser
uv run python manage.py createsuperuser

# Run the development server
uv run python manage.py runserver

Visit http://localhost:8000 to see your portal!


📦 Core Concepts

Projects, Datasets, Samples & Measurements

FairDM organizes research data using a hierarchical structure:

Project
└── Dataset
    ├── Sample (your custom types)
    │   └── Measurement (your custom types)
    └── Sample
        └── Measurement
  • Project: Top-level container for research initiatives
  • Dataset: Collection of related samples with shared metadata
  • Sample: Domain-specific sample types (e.g., RockSample, WaterSample)
  • Measurement: Domain-specific measurements on samples (e.g., XRFMeasurement)

Portal Configuration

A portal gets its entire Django configuration from one call:

# config/settings.py
import fairdm

fairdm.setup(apps=["myportal"], addons=["fairdm_discussions"])

FairDM's settings are production-grade in every environment. Each environment is an override layered on top, named by DJANGO_ENV and applied only if it exists — so config/development.py beside your settings module tunes development, and an environment nobody ships a module for simply gets the production baseline. In production, configuration that would leave the portal unsafe stops it starting.

See Configuration for the layer order, the environment variables and manage.py show_config.

Model Registration

The heart of FairDM is its registry system. Define your models, register them, and get automatic:

  • ✅ Create/Read/Update/Delete views
  • ✅ List tables with sorting and filtering
  • ✅ Forms with Bootstrap 5 styling
  • ✅ REST API endpoints (optional)
  • ✅ Import/Export functionality
  • ✅ Admin integration

Example: Registering a Custom Sample

# myapp/models.py
from fairdm.core.models import Sample
from django.db import models

class RockSample(Sample):
    """Custom sample type for geological specimens."""

    rock_type = models.CharField(max_length=100)
    collection_date = models.DateField()
    weight_grams = models.DecimalField(max_digits=10, decimal_places=2)


# myapp/config.py
from fairdm.core.sample.config import BaseSampleConfiguration
from fairdm.registry import register
from .models import RockSample

@register
class RockSampleConfig(BaseSampleConfiguration):
    model = RockSample
    fields = ["name", "rock_type", "collection_date", "weight_grams", "location"]

Listing location gives the type's form the location input, which reads signed decimal degrees in WGS 84.

BaseSampleConfiguration is the recommended base for a specimen type's registry configuration — it declares the shared fields list every generated component falls back to, so you only state it once. A configuration that relies on the registry auto-detecting a different field list per component (table vs. form vs. filter set) should subclass the plain ModelConfiguration instead.

That's it! You now have:

  • A working web interface for managing rock samples
  • Sortable/filterable tables
  • Create/update/delete forms
  • Import/export to CSV/Excel
  • REST API endpoints (if enabled)

🎨 Features

✨ Auto-Generated Components

For every registered model, FairDM automatically generates:

Component Library Purpose
Forms Django Forms + Crispy Forms Create/edit with Bootstrap 5 styling
Tables django-tables2 Sortable, paginated lists
Filters django-filter Advanced filtering UI
Serializers Django REST Framework JSON API responses
Resources django-import-export CSV/Excel import/export
Admin Django Admin Optional admin interface

🔐 Permissions & Access Control

  • Object-level permissions via django-guardian
  • Role-based access (viewer, editor, manager) at Project/Dataset level
  • Public/private dataset visibility controls
  • Add contributors to a project or dataset, including unclaimed profiles for people without accounts yet

📊 Data Import/Export

  • Formats: CSV, Excel (XLSX), JSON, ODS
  • Background processing: Large imports via Celery tasks
  • Validation: Automatic field validation and error reporting
  • Templates: Export sample templates for data collection

🔌 Plugin System

Extend FairDM with custom functionality:

  • Add analysis panels to detail views
  • Create custom visualizations
  • Integrate third-party tools
  • Build domain-specific workflows

🌍 Modern Frontend Stack

  • django-mvp — Shared application shell built on Tailwind CSS and daisyUI
  • daisy-cotton-ext — Page blocks the landing page is built from
  • django-mvp-compliance — Legal documents kept in the database, and a record of who agreed to them
  • HTMX — Dynamic interactions without writing JavaScript
  • Alpine.js — Lightweight reactivity for complex interactions
  • Django Cotton — Reusable component-based templates

📚 Documentation

Full documentation is available at: https://fairdm.readthedocs.io/en/latest/

Documentation Sections

  • Developers — Build and deploy a research portal on FairDM
  • Administrators — Run a portal: people, roles, content review and configuration checks
  • Users — Add, edit and publish research data in a portal
  • Contributing — Contribute to FairDM framework development

🧪 Demo Application

Explore a working example in the demo/ directory:

# The demo app showcases:
# - Custom Sample and Measurement models
# - Model registration and configuration
# - Custom forms, tables, and filters
# - Plugin development examples

The demo app serves as executable documentation and demonstrates best practices for building portals with FairDM.


🛠️ Development

Running Tests

# Run the full test suite
uv run pytest

# Run with coverage
uv run pytest --cov=fairdm --cov-report=html

# Run specific test file
uv run pytest tests/test_registry/test_config.py

# Run the reference application's tests on their own (they run by default too)
uv run pytest demo/tests

# Run with verbose output
uv run pytest -v

# Run in a single process (tests are parallel by default)
uv run pytest -n0

Code Quality

FairDM uses Ruff for linting and formatting:

# Lint the codebase
uv run ruff check .

# Format code
uv run ruff format .

# Check type hints with mypy
uv run mypy fairdm

Project Commands

Useful Invoke tasks (see tasks.py):

# Show available tasks
uv run invoke -l

# Run database migrations
uv run invoke migrate

# Create test data
uv run invoke create-test-data

# Build documentation
uv run invoke docs

🏗️ Technology Stack

Core Framework

  • Django 6.0 — Web framework
  • Python 3.13+ — Programming language
  • PostgreSQL — Database (recommended)
  • Redis — Caching and task queue

Key Dependencies

  • django-polymorphic — Polymorphic model inheritance
  • django-guardian — Object-level permissions
  • django-tables2 — Table rendering
  • django-filter — Filtering system
  • django-import-export — Data import/export
  • django-htmx — HTMX integration
  • django-cotton — Component-based templates
  • celery — Background task processing

See pyproject.toml for the complete dependency list.


Changelog

See CHANGELOG.md.

📄 License

This project is licensed under the MIT License — see the LICENSE file for details.


🤝 Contributing

We welcome contributions! See our Contributing Guide for:

  • Development workflow: Install git hooks to prevent CI failures
  • Code style and conventions: Ruff formatting (120 char lines)
  • Testing requirements: pytest with >80% coverage goal
  • Pull request process: Pre-push validation ensures CI passes

Before your first push, install git hooks to run CI checks locally:

uv run invoke install-hooks

This prevents CI failures by running the same linting and formatting checks locally.


🌟 Project Status

FairDM is under active development. Current focus areas:

  • ✅ Core framework and registry system
  • ✅ Model registration and auto-generation
  • ✅ Permissions and access control
  • 🚧 Plugin system expansion
  • 🚧 REST API enhancements
  • 🚧 Advanced data visualization
  • 📋 Cloud deployment guides
  • 📋 Extended documentation

📞 Support & Community


Made with ❤️ for the research community

Metadata

Release files for fairdm 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fairdm 0.3.0
File Size Uploaded Provenance Actions
fairdm-0.3.0.tar.gz 682.3 kB With provenance Details for fairdm-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for fairdm 0.3.0
File Interpreter ABI Platform Actions
fairdm-0.3.0-py3-none-any.whl Python 3 none any Details for fairdm-0.3.0-py3-none-any.whl

Total release size: 1.6 MB

Release files / fairdm-0.3.0.tar.gz

Download URL fairdm-0.3.0.tar.gz
Size 682.3 kB
Tags Source
SHA-256 checksum
How to use checksums
44fc264282133c0e1b4f1dc9cc5cdb105cda7e228035e0ce6620f3a6a1311ed2
BLAKE2b-256 checksum
How to use checksums
b2258497bc1701d19764c5c70060a5de9aa5ed84e64036b4900314e6decc9540
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 28, 2026.

Transparency log

Release files / fairdm-0.3.0-py3-none-any.whl

Download URL fairdm-0.3.0-py3-none-any.whl
Size 911.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
75dd89006e885f248db7e5ac710f1fc51870f81006c7a8bab2ca47873b28d3f1
BLAKE2b-256 checksum
How to use checksums
865f74d7bdcc192f58b281b7e764f158d058059d8da33f16acf4a4503291db5d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 28, 2026.

Transparency log

Security for fairdm 0.3.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.

Select from 2 files

Attestation for fairdm-0.3.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 Oct 28, 2026.

Transparency log

A 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.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page