Skip to content

Getting Started

Ready after setup?

Once you have the basics installed, continue with Setup & Core CRUD basics for the full walkthrough. After you have seen the main features, read PowerCRUD Concepts to put the configuration model in perspective.

Installation

Install Python packages

pip install neapolitan
pip install django-powercrud

Optional add-on:

  • If you want saved favourites, also add the optional contrib app to INSTALLED_APPS, run migrations, and mount powercrud.urls with namespace powercrud.
  • The detailed behavior and UI guidance live in Saved Favourites.

Dependencies

Backend dependencies

Install django-powercrud and neapolitan via pip, then add the required Django apps and middleware in your settings.

PowerCRUD installs these Python dependencies automatically:

  • django-htmx
  • django-template-partials for Django 5.2 template partial compatibility
  • pydantic
Backend library docs

Frontend dependencies

PowerCRUD ships package-owned frontend runtime assets and a packaged bundle.

Runtime responsibilities include:

  • HTMX
  • Tom Select (searchable single/multi select enhancement)
  • Tippy.js (truncated-table tooltips/popovers)
  • PowerCRUD runtime JS/CSS (powercrud/js/powercrud.js, powercrud/css/powercrud.css)

You can run PowerCRUD in either of these modes:

  • Bundled mode (recommended): load PowerCRUD's packaged Vite entry (config/static/js/main.js).
  • Manual mode: install frontend dependencies yourself, then load PowerCRUD runtime assets from Django static paths.
Frontend library docs

Projects that use the built-in templates but manage assets manually should read those docs. Projects that load the packaged bundle can usually ignore package-level frontend dependency wiring.

Required Configuration

Minimum required wiring for PowerCRUD

PowerCRUD depends on these Django integrations:

  • Add to INSTALLED_APPS: powercrud, neapolitan, django_htmx
  • On Django 5.2 only, also add template_partials
  • Add to MIDDLEWARE: django_htmx.middleware.HtmxMiddleware
  • Load the PowerCRUD frontend bundle in your base template, or provide equivalent frontend assets yourself
  • pydantic is installed automatically and needs no extra Django setup

If django_htmx.middleware.HtmxMiddleware is missing, HTMX requests will fail at runtime.

Add to your settings.py:

# Required settings
import django


POWERCRUD_COMPAT_APPS = []
if django.VERSION < (6, 0):
    POWERCRUD_COMPAT_APPS.append("template_partials")

INSTALLED_APPS = [
    ...
    "powercrud",
    "neapolitan",
    "django_htmx",
    *POWERCRUD_COMPAT_APPS,
    ...
]

MIDDLEWARE = [
    ...,
    "django_htmx.middleware.HtmxMiddleware",
    ...,
]

# Optional: POWERCRUD_SETTINGS overrides (all keys are optional and have defaults)
POWERCRUD_SETTINGS = {
    "POWERCRUD_CSS_FRAMEWORK": "daisyui",  # built-in default
}

If your own templates define partials and need to support both Django 5.2 and 6.0, load PowerCRUD's compatibility tag library:

{% load powercrud_partials %}
{% partialdef toolbar %}
    ...
{% endpartialdef toolbar %}
{% partial toolbar %}

Django 6.0 includes template partials in core, so do not add template_partials to INSTALLED_APPS on Django 6 projects.

If you want the optional saved favourites feature:

INSTALLED_APPS = [
    ...,
    "powercrud.contrib.favourites",
]
python manage.py migrate
urlpatterns = [
    # ...
    path("powercrud/", include("powercrud.urls", namespace="powercrud")),
]

The URL prefix can be different, but the namespace must stay powercrud.

If you do not install that contrib app and mount its shared URLs, filtering still works normally and the favourites UI simply remains unavailable.

Frontend Integration

You can install PowerCRUD in two ways.

Use the packaged bundle to keep setup small and behaviour aligned with docs.

When using django-vite, configure a dedicated app entry for PowerCRUD:

# settings.py
from importlib import resources


POWERCRUD_ASSETS_DIR = resources.files("powercrud").joinpath("assets")
STATIC_URL = "/static/"
STATICFILES_DIRS = [
    # your existing static dirs...
    str(POWERCRUD_ASSETS_DIR),
]

DJANGO_VITE = {
    "default": {
        # Your project's own frontend bundle config
    },
    "powercrud": {
        "dev_mode": False,
        "static_url_prefix": "/static/",
        "manifest_path": str(POWERCRUD_ASSETS_DIR / "manifest.json"),
    },
}

Then load the bundle entry in your base template:

{% load django_vite %}
{% vite_asset 'config/static/js/main.js' app='powercrud' %}

See sample/templates/sample/daisyUI/base.html for a complete Vite-based example.

If your page also loads your app's own bundle, both lines can coexist:

{% vite_asset 'src/config/static/js/main.js' %}
{% vite_asset 'config/static/js/main.js' app='powercrud' %}

Bundle mode checks:

  • Generated PowerCRUD asset URLs should be absolute, for example /static/django_assets/....
  • Ensure global STATIC_URL is absolute, for example "/static/".
  • If URLs appear relative (for example static/django_assets/... resolving to /your/page/path/static/...), set static_url_prefix to "/static/".
  • Ensure POWERCRUD_ASSETS_DIR is registered in STATICFILES_DIRS so static lookup can find django_assets/powercrud-*.js|css.

Projects that do not use django.contrib.staticfiles are especially sensitive here: static_url_prefix and STATICFILES_DIRS become mandatory for reliable packaged-bundle resolution.

If you manage frontend dependencies yourself, you must:

  1. Load vendor dependencies (HTMX, Tom Select, Tippy.js).
  2. Expose them as browser globals.
  3. Load PowerCRUD runtime assets.

Template example:

{% load static %}

<link rel="stylesheet" href="{% static 'powercrud/css/powercrud.css' %}">

<script src=".../htmx.min.js"></script>
<link rel="stylesheet" href=".../tom-select.default.min.css">
<script src=".../tom-select.complete.min.js"></script>
<script src=".../tippy-bundle.umd.min.js"></script>
<script type="module" src="{% static 'powercrud/js/powercrud.js' %}"></script>

If your project uses a JS bundler (for example Vite/Webpack) for vendor packages, expose globals in your app entry:

import htmx from "htmx.org";
import TomSelect from "tom-select";
import removeButtonPlugin from "tom-select/dist/js/plugins/remove_button.js";
import "tom-select/dist/css/tom-select.css";
import tippy from "tippy.js";
import "tippy.js/dist/tippy.css";

window.htmx = htmx;
TomSelect.define("remove_button", removeButtonPlugin);
window.TomSelect = TomSelect;
window.tippy = tippy;

Then load PowerCRUD runtime assets in your base template:

{% load static %}
<link rel="stylesheet" href="{% static 'powercrud/css/powercrud.css' %}">
<script type="module" src="{% static 'powercrud/js/powercrud.js' %}"></script>

Manual mode requirements:

  • Load vendor dependencies before the module entry at powercrud/js/powercrud.js.
  • Load only the stable module entry; the browser follows PowerCRUD's internal module imports.
  • Load Tom Select's vendor CSS before powercrud/css/powercrud.css so the package can override Tom Select with daisyUI semantic colors.
  • Register the Tom Select remove_button plugin if you want multi-select remove buttons.
  • If you use built-in daisyUI templates without the packaged bundle, you must provide your own daisyUI/Tailwind CSS stack.

Do not load both integration modes on the same page:

  • Use either the packaged bundle ({% vite_asset 'config/static/js/main.js' app='powercrud' %}), or:
  • Manual vendor/runtime assets.

Quick browser verification for manual mode:

Boolean(window.initPowercrudSearchableSelects) // true
Boolean(window.TomSelect)                      // true
Boolean(window.htmx)                           // true

If fields have data-powercrud-searchable-select="true" but no Tom Select UI appears, the runtime script is not loaded or window.TomSelect is missing.

Important: If you compile Tailwind yourself, ensure Tailwind includes PowerCRUD classes in its build process. See the Styling guide for details.

Quick Start Tutorial

Basic Setup

Start with a basic CRUD view. For reference see neapolitan's docs.

from powercrud.mixins import PowerCRUDMixin
from neapolitan.views import CRUDView
from . import models

class ProjectCRUDView(PowerCRUDMixin, CRUDView):
    model = models.Project
    fields = ["name", "owner", "last_review", "status"]
    base_template_path = "core/base.html"

Add to URLs

PowerCRUD’s UrlMixin (inherited from Neapolitan) exposes get_urls() so you do not have to hand-write the five CRUD routes. Pick the style that suits your project:

from django.urls import path, include
from neapolitan.views import Role
from .views import ProjectCRUDView

app_name = "my_app"  # keep namespaces aligned with your include()

urlpatterns = []
urlpatterns += ProjectCRUDView.get_urls()

If you prefer the unpack pattern:

urlpatterns = [
    *ProjectCRUDView.get_urls(),
]

Need fewer routes (and therefore fewer action buttons)? Limit the registered roles:

urlpatterns = [
    *ProjectCRUDView.get_urls(roles={Role.LIST, Role.DETAIL}),
]

Only the List and View endpoints (and their buttons) will render in that case. Finally, include the app URLs at the project level as usual:

# config/urls.py
from django.urls import include, path

urlpatterns = [
    path("projects/", include("my_app.urls")),
]

Your First Enhanced View

Add some powercrud features:

class ProjectCRUDView(PowerCRUDMixin, CRUDView):
    model = models.Project
    base_template_path = "core/base.html"

    # Basic field control
    fields = ["name", "owner", "status", "created_date"]
    properties = ["is_overdue"]  # Include @property fields

    # Enable modern features
    use_htmx = True
    use_modal = True

    # Add filtering
    filterset_fields = ["owner", "status", "created_date"]

    # Enable pagination
    paginate_by = 25

    # Optional: namespace for URLs
    namespace = "my_app"

That's it! You now have a fully-featured CRUD interface with filtering, pagination, modals, and HTMX support.

Next Steps