# django-tasks

> A backport of Django's built in Tasks framework

- **URL**: https://www.freshcrate.ai/projects/django-tasks
- **Author**: Jake Howard
- **Category**: Frameworks
- **Latest version**: `0.12.0` (2026-04-21)
- **License**: Unknown
- **Source**: https://github.com/RealOrangeOne/django-tasks/releases
- **Homepage**: https://pypi.org/project/django-tasks/
- **Language**: Python
- **GitHub**: 799 stars, 54 forks
- **Registry**: pypi (`django-tasks`)
- **Tags**: `pypi`

## Description

# Django Tasks

[![CI](https://github.com/RealOrangeOne/django-tasks/actions/workflows/ci.yml/badge.svg)](https://github.com/RealOrangeOne/django-tasks/actions/workflows/ci.yml)
![PyPI](https://img.shields.io/pypi/v/django-tasks.svg)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/django-tasks.svg)
![PyPI - Status](https://img.shields.io/pypi/status/django-tasks.svg)
![PyPI - License](https://img.shields.io/pypi/l/django-tasks.svg)

An backport of `django.tasks` - Django's built-in [Tasks framework](https://docs.djangoproject.com/en/stable/topics/tasks/).

## Installation

```
python -m pip install django-tasks
```

The first step is to add `django_tasks` to your `INSTALLED_APPS`.

```python
INSTALLED_APPS = [
    # ...
    "django_tasks",
]
```

Secondly, you'll need to configure a backend. This connects the tasks to whatever is going to execute them.

If omitted, the following configuration is used:

```python
TASKS = {
    "default": {
        "BACKEND": "django_tasks.backends.immediate.ImmediateBackend"
    }
}
```

A few backends are included by default:

- `django_tasks.backends.dummy.DummyBackend`: Don't execute the tasks, just store them. This is especially useful for testing.
- `django_tasks.backends.immediate.ImmediateBackend`: Execute the task immediately in the current thread

Prior to `0.12.0`, [`django-tasks-db`](https://github.com/RealOrangeOne/django-tasks-db) and [`django-tasks-rq`](https://github.com/RealOrangeOne/django-tasks-rq) were also included to provide database and RQ based backends.

## Usage

### Defining tasks

A task is created with the `task` decorator.

```python
from django_tasks import task


@task()
def calculate_meaning_of_life() -> int:
    return 42
```

The task decorator accepts a few arguments to customize the task:

- `priority`: The priority of the task (between -100 and 100. Larger numbers are higher priority. 0 by default)
- `queue_name`: Whether to run the task on a specific queue
- `backend`: Name of the backend for this task to use (as defined in `TASKS`)

```python
modified_task = calculate_meaning_of_life.using(priority=10)
```

In addition to the above attributes, `run_after` can be passed to specify a specific time the task should run.

#### Task context

Sometimes the running task may need to know context about how it was enqueued. To receive the task context as an argument to your task function, pass `takes_context` to the decorator and ensure the task takes a `context` as the first argument.

```python
from django_tasks import task, TaskContext


@task(takes_context=True)
def calculate_meaning_of_life(context: TaskContext) -> int:
    return 42
```

The task context has the following attributes:

- `task_result`: The running task result
- `attempt`: The current attempt number for the task

This API will be extended with additional features in future.

### Enqueueing tasks

To execute a task, call the `enqueue` method on it:

```python
result = calculate_meaning_of_life.enqueue()
```

The returned `TaskResult` can be interrogated to query the current state of the running task, as well as its return value.

If the task takes arguments, these can be passed as-is to `enqueue`.

### Queue names

By default, tasks are enqueued onto the "default" queue. When using multiple queues, it can be useful to constrain the allowed names, so tasks aren't missed.

```python
TASKS = {
    "default": {
        "BACKEND": "django_tasks.backends.immediate.ImmediateBackend",
        "QUEUES": ["default", "special"]
    }
}
```

Enqueueing tasks to an unknown queue name raises `InvalidTaskError`.

To disable queue name validation, set `QUEUES` to `[]`.

### Retrieving task result

When enqueueing a task, you get a `TaskResult`, however it may be useful to retrieve said result from somewhere else (another request, another task etc). This can be done with `get_result` (or `aget_result`):

```python
result_id = result.id

# Later, somewhere else...
calculate_meaning_of_life.get_result(result_id)
```

A result `id` should be considered an opaque string, whose length could be up to 64 characters. ID generation is backend-specific.

Only tasks of the same type can be retrieved this way. To retrieve the result of any task, you can call `get_result` on the backend:

```python
from django_tasks import default_task_backend

default_task_backend.get_result(result_id)
```

### Return values

If your task returns something, it can be retrieved from the `.return_value` attribute on a `TaskResult`. Accessing this property on an unsuccessful task (ie not `SUCCESSFUL`) will raise a `ValueError`.

```python
assert result.status == TaskResultStatus.SUCCESSFUL
assert result.return_value == 42
```

If a result has been updated in the background, you can call `refresh` on it to update its values. Results obtained using `get_result` will always be up-to-date.

```python
assert result.status == TaskResultStatus.READY
result.refresh()
assert result.status == TaskResultStatus.SUCCESSFUL

## Recent releases

| Version | Date | Urgency | Changes |
| --- | --- | --- | --- |
| `0.12.0` | 2026-04-21 | Low | Imported from PyPI (0.12.0) |
| `0.11.0` | 2026-01-09 | Low | ## What's Changed * Add [task metadata](https://github.com/RealOrangeOne/django-tasks/?tab=readme-ov-file#metadata) by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/212. Useful for building additional functionality on top of tasks * fix small typo by @psadil in https://github.com/RealOrangeOne/django-tasks/pull/221 * Cancelled previous runs and run only latest one in CI by @p-r-a-v-i-n in https://github.com/RealOrangeOne/django-tasks/pull/217 * Fix runtime instantiatio |
| `0.10.0` | 2025-12-03 | Low | ## Breaking changes  * Remove `enqueue_on_commit` functionality by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/194  ## What's Changed * Test against Django 6.0 in CI by @mportesdev * Add Python 3.14 support in CI by @p-r-a-v-i-n in https://github.com/RealOrangeOne/django-tasks/pull/198 * Set import path of mocked function conditionally by @mportesdev in https://github.com/RealOrangeOne/django-tasks/pull/207  ## New Contributors * @p-r-a-v-i-n made their first c |
| `0.9.0` | 2025-10-17 | Low | ## What's Changed  - fix: prevent `IndexError: pop from empty list` in RQ backend by @crgwbr in https://github.com/RealOrangeOne/django-tasks/pull/183 - Add support for Django 6.0 by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/193 - Add `supports_priority` feature - Access RQ worker name from result, rather than smuggling through meta (requires RQ 2.5+) - Correctly handle unserializable return values in RQ backend - Optimise job fetching in RQ backend  ### Break |
| `0.8.1` | 2025-07-04 | Low | ## What's Changed * Fix timezone support for run_after DATE_MAX by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/179  **Full Changelog**: https://github.com/RealOrangeOne/django-tasks/compare/0.8.0...0.8.1  If you haven't yet updated to 0.8.0, it's recommended to upgrade straight to 0.8.1. |
| `0.8.0` | 2025-06-24 | Low | ## Breaking changes  * The task status `NEW` has been renamed to `READY`, to better support future retry functionality. Existing tasks are automatically migrated * Exceptions and tracebacks are moved to a `.errors` list, rather than being on the `TaskResult` directly. This allows multiple errors to be tracked  ## Notable changes  * Add DB indexes by @RealOrangeOne & @jonatron in https://github.com/RealOrangeOne/django-tasks/pull/155 :zap:  * Add started signal by @RealOrangeOne in https: |
| `0.7.0` | 2025-04-27 | Low | ## What's Changed * Don't require exclusive transactions for entire SQLite DB by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/132 - Users can now remove the `TRANSACTION_MODE = "EXCLUSIVE"` for the entire database connection. * Support auto-reloading of database worker by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/152 * Add RQ backend by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/151 * Add support for Django 5.2 by @ |
| `0.6.1` | 2024-12-27 | Low | ## What's Changed * Fix README for `.exception_class` by @tomkins in https://github.com/RealOrangeOne/django-tasks/pull/128 * Add a task_name property to DBTaskResult by @tomkins in https://github.com/RealOrangeOne/django-tasks/pull/127 * Allow ./manage.py without args by @jonatron in https://github.com/RealOrangeOne/django-tasks/pull/130 * Ensure return value is correctly exposed using database backend by @RealOrangeOne in 22d51b37ccbdd52245400f1eee79fb551de7c8d2  ## New Contributors * @ |
| `0.6.0` | 2024-11-29 | Low | ## What's Changed * Add explicit support for Python 3.13 by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/112 * Don't enforce UUIDs for task ids by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/120 * (breaking) Rename "completed" tasks to "succeeded" by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/119 * (breaking) Simplify exception serialization to avoid issues with complex exceptions by @RealOrangeOne in https://github.c |
| `0.5.0` | 2024-09-19 | Low | ## What's Changed * Update result to have separate attributes for return value and exception by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/103 * Prevent writing to task results by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/106 * Add additional test cases for process management by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/88 * Add Django 5.1+ support for `CheckConstraint condition` with backward compatibility by @s |

## Citation

- HTML: https://www.freshcrate.ai/projects/django-tasks
- Markdown: https://www.freshcrate.ai/projects/django-tasks.md
- Dependencies JSON: https://www.freshcrate.ai/api/projects/django-tasks/deps

_Generated by freshcrate.ai. Indexes pypi releases for AI-agent ecosystem packages._
