Skip to main content

weft-django

weft-django is the first-party Django integration for Weft.

The package is typed (py.typed) and depends on Weft through the public weft.client API.

It provides:

  • @weft_task for Django-owned synchronous background functions
  • transaction-safe submission helpers such as enqueue_on_commit()
  • native TaskSpec, stored spec, and pipeline submission helpers
  • read-only Django URLs for task inspection
  • SSE by default, with optional Channels/WebSocket transport
  • Django management commands for task status and control

Install:

uv add weft-django

Or from the main package convenience extra:

uv add "weft[django]"

Install the optional Channels transport with:

uv add "weft-django[channels]"

Equivalent install surfaces:

uv add "weft-django[realtime]"
uv add "weft[django-channels]"

Basic usage:

from weft_django import weft_task


@weft_task(name="billing.send_invoice", timeout=60)
def send_invoice(invoice_id: int) -> dict[str, int]:
    return {"invoice_id": invoice_id}


submission = send_invoice.enqueue(123)
result = submission.result(timeout=30)
assert result.status == "completed"

Project Context

Django requests its runtime context from Weft. With no explicit context setting, Weft discovers the nearest project starting at Django's BASE_DIR, using that directory itself when discovery finds nothing:

# settings.py
INSTALLED_APPS += ["weft_django"]
WEFT_DJANGO = {}

To pin a project explicitly, set WEFT_DJANGO = {"CONTEXT": BASE_DIR}. The explicit Django setting wins over WEFT_CONTEXT. Otherwise WEFT_CONTEXT selects the root before discovery from BASE_DIR. Without BASE_DIR, Weft uses its ordinary CWD discovery. Explicit roots are used directly; they are not discovery anchors.

Broker settings such as WEFT_BACKEND_TARGET select the broker while preserving this project-root policy. For example, a PostgreSQL target does not move Weft's artifact directory to the web worker's CWD. Project broker configuration retains its existing precedence. BROKER_* variables do not configure Weft.

Settings import and task discovery do not initialize Weft. Runtime operations acquire a client with a resolved context and Config snapshot; a retained client keeps that snapshot, while a later acquisition can observe new settings.

After upgrading, stray BROKER_* or default-valued broker settings no longer redirect Django's artifacts to CWD. If an installation used that former destination, pin CONTEXT to its existing root before upgrading. The integration does not move existing tasks or artifacts. Restart long-lived Django processes to pick up the new code and settings.

Submission Handle

enqueue(...) and the native submission helpers return WeftSubmission.

The handle exposes:

  • tid
  • name
  • status()
  • wait(timeout=None)
  • result(timeout=None)
  • stop()
  • kill()
  • events(follow=False)

status() returns the current public status string or None if no snapshot is available yet. wait() and result() both return the structured Weft TaskResult.

Module-level status(tid) and terminal_snapshot(tid) use Weft's compact known-TID terminal snapshot path. They are read-only and can report terminal Monitor-store fallback after raw task-log rows retire. Use snapshot(tid) when callers need diagnostic fields such as task metadata, runtime details, or timestamps.

enqueue_on_commit(...) and the native *_on_commit(...) helpers return WeftDeferredSubmission. The deferred handle has a stable name immediately and gains tid plus task methods after the outer transaction commits. Calling result-like methods before commit raises a local RuntimeError.

A successful Weft broker write binds the deferred TID even if manager readiness then degrades. That readiness warning does not raise from the commit callback or stop later callbacks. Broker-write failure and authoritative manager rejection still raise. The hook is not a durable outbox or an atomic cross-database write.

Deferred helpers validate and snapshot before registering Django's transaction.on_commit() callback. Missing spec references, invalid overrides, and unserializable payloads fail before the app transaction commits. Mutating args, kwargs, or payload objects after helper call time does not change the work submitted at commit.

The helpers also capture the core client before registering the callback. Changing Django settings, environment, CWD, or HOME before commit does not redirect prepared work. Core preparation binds an explicit relative or home-relative TaskSpec context to its absolute path. An explicitly different TaskSpec root still has its broker selected at submission using captured Config; broker project files are not snapshotted.

Composition Export

task.as_taskspec_for_call(*args, _overrides=None, **kwargs) returns the validated, normalized TaskSpec definition for that call, with the call envelope embedded in spec.args, for manual composition into ordinary Weft task or pipeline specs. It does not submit anything, builds no Weft context, reads no Weft configuration, opens no broker, and writes nothing (the configured REQUEST_ID_PROVIDER still runs, as it does for every call). _overrides accepts exactly Weft's public submit overrides (name, description, tags, env, working_dir, stream_output, timeout, memory_mb, cpu_percent, runner, runner_options, metadata) with core semantics: None values are ignored, unknown names (including wait) raise TypeError, and invalid values raise the TaskSpec validation error. The export is weft.client.normalize_taskspec_payload(...) applied to the generated template; the package applies no overrides of its own.

An explicit Django CONTEXT is copied into spec.weft_context as declared, including relative or home-relative text. With no explicit setting, the field remains unset: the export does not capture BASE_DIR, environment, or a discovered project. Such exports inherit their destination from the receiving Weft context when submitted or composed. This makes exports portable; set CONTEXT explicitly when the declaration must name a particular project.

Native Helpers

Use these helpers when Django code wants to launch native Weft work instead of a decorated Django function:

from pathlib import Path

from weft_django import (
    submit_pipeline_reference,
    submit_spec_reference,
    submit_taskspec,
)


task = submit_taskspec(taskspec, payload={"job": 1})
task = submit_spec_reference(Path(".weft/tasks/report.json"), payload={"job": 1})
task = submit_pipeline_reference("nightly-report", payload={"job": 1})

Keyword rules:

  • native helpers use payload=...
  • work_payload=... and input=... are intentionally not supported
  • deferred helpers reject wait=True

Testing

weft-django does not ship an eager or inline execution mode.

Use the direct Python callable for narrow unit tests:

assert send_invoice(123)["invoice_id"] == 123

Use broker-backed tests for enqueue behavior, transaction hooks, process boundaries, streaming, native TaskSpecs, bundles, agents, and pipelines.

Realtime And URLs

Include the read-only URLs explicitly:

from django.urls import include, path

urlpatterns = [
    path("weft/", include("weft_django.urls")),
]

You must configure an authz callable:

WEFT_DJANGO = {
    "AUTHZ": "myapp.weft_authz:authorize",
}

Supported realtime settings:

WEFT_DJANGO = {
    "REALTIME": {
        "TRANSPORT": "sse",  # "none" | "sse" | "channels"
    },
}

Notes:

  • GET /weft/tasks/<tid>/ returns the current task snapshot
  • GET /weft/tasks/<tid>/events/ is the SSE endpoint when TRANSPORT="sse"
  • TRANSPORT="none" disables the SSE endpoint
  • TRANSPORT="channels" switches browser realtime delivery to the optional WebSocket consumer in weft_django.channels
  • the Channels consumer starts a cancellable background stream after socket accept rather than blocking the connect lifecycle
  • the HTTP and realtime surfaces are diagnostics only; they do not create a second task-truth store

Celery Migration Guide

Celery habit weft-django
@shared_task @weft_task
task.delay(...) task.enqueue(...)
transaction.on_commit(lambda: task.delay(...)) task.enqueue_on_commit(...)
AsyncResult WeftSubmission

delay and shared_task are intentionally not shipped. They are close enough to invite mechanical porting and far enough from Weft semantics to create delayed failures.

Release files for weft-django 0.9.40

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

Source distribution (sdist)

Source distribution for weft-django 0.9.40
File Size Uploaded
weft_django-0.9.40.tar.gz 17.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for weft-django 0.9.40
File Interpreter ABI Platform
weft_django-0.9.40-py3-none-any.whl Python 3 none any Details

Total release size: 45.6 kB

Release files / weft_django-0.9.40.tar.gz

Download URL weft_django-0.9.40.tar.gz
Size 17.5 kB
Tags Source
SHA-256 checksum
How to use checksums
e681f17baecca3341f8dbc43aa146cb846b2fd5741969b6cff9724c8d917346f
BLAKE2b-256 checksum
How to use checksums
428825e5703f815d824728b1284da254de0047ab64b9070067fdf473f067b501
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / weft_django-0.9.40-py3-none-any.whl

Download URL weft_django-0.9.40-py3-none-any.whl
Size 28.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c3304ddf251c8124843f305e2c3ad9b96a266beeab4e665fb9e1e48c83c6216f
BLAKE2b-256 checksum
How to use checksums
ab908067f580fe799bfbf1637fa33dfa07c03c37ecefa265fab4326dfb8fcf3b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.9.42

2 release files

0.9.41

2 release files

This release

0.9.40 This release

2 release files

0.9.39

2 release files

0.9.38

2 release files

0.9.37

2 release files

0.9.36

2 release files

0.9.35

2 release files

0.9.33

2 release files

0.9.32

2 release files

0.9.30

2 release files

0.9.6

2 release files

0.9.5

2 release files

0.9.4

2 release files

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