Description
# Django Tasks [](https://github.com/RealOrangeOne/django-tasks/actions/workflows/ci.yml)     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
Release History
| Version | Changes | Urgency | Date |
|---|---|---|---|
| 0.12.0 | Imported from PyPI (0.12.0) | Low | 4/21/2026 |
| 0.11.0 | ## 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 | Low | 1/9/2026 |
| 0.10.0 | ## 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 | Low | 12/3/2025 |
| 0.9.0 | ## 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 | Low | 10/17/2025 |
| 0.8.1 | ## 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. | Low | 7/4/2025 |
| 0.8.0 | ## 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: | Low | 6/24/2025 |
| 0.7.0 | ## 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 @ | Low | 4/27/2025 |
| 0.6.1 | ## 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 * @ | Low | 12/27/2024 |
| 0.6.0 | ## 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 | Low | 11/29/2024 |
| 0.5.0 | ## 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 | Low | 9/19/2024 |
| 0.4.0 | ## What's Changed * Swallow and log any BaseException in ImmediateBackend other than KeyboardInterrupt by @jhthompson in https://github.com/RealOrangeOne/django-tasks/pull/81 * Hard stop worker by sending ctrl-c twice by @mgax in https://github.com/RealOrangeOne/django-tasks/pull/86 * Allow fractional interval argument for database worker by @mgax in https://github.com/RealOrangeOne/django-tasks/pull/83 * Close connections after each task by @RealOrangeOne in https://github.com/RealOrangeOne | Low | 8/12/2024 |
| 0.3.0 | ## What's Changed * Remove close method by @knyghty in https://github.com/RealOrangeOne/django-tasks/pull/61 * Run tests on Windows and macOS by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/65 * Add task starting datetimes to TaskResults by @Vidski in https://github.com/RealOrangeOne/django-tasks/pull/67 * Store task exceptions by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/68 * Define priority range and semantics by @RealOrangeOne in https:/ | Low | 7/16/2024 |
| 0.2.0 | ## What's Changed * Use modules in justfile by @pauloxnet in https://github.com/RealOrangeOne/django-tasks/pull/43 * Add extras for database dependencies by @pauloxnet in https://github.com/RealOrangeOne/django-tasks/pull/41 * Update git action versions by @pauloxnet in https://github.com/RealOrangeOne/django-tasks/pull/45 * Using the DEFAULT_TASK_BACKEND_ALIAS constant by @dennisstritzke in https://github.com/RealOrangeOne/django-tasks/pull/36 * Adding completion datetimes to the TaskResul | Low | 6/21/2024 |
| 0.1.1 | Fixes an issue of a missing migration to change `verbose_name` for the database backend. There should be no other changes in functionality. **Full Changelog**: https://github.com/RealOrangeOne/django-tasks/compare/0.1.0...0.1.1 | Low | 6/8/2024 |
| 0.1.0 | ## What's Changed * Allow tasks to be called directly * Add caution about SQLite concurrency * Fixup badges in the README by @sobolevn in https://github.com/RealOrangeOne/django-tasks/pull/4 * Database backend by @RealOrangeOne in https://github.com/RealOrangeOne/django-tasks/pull/3 :rocket: * Removing the mail backend by @dennisstritzke in https://github.com/RealOrangeOne/django-tasks/pull/34 * Add `django-stubs` dependency by @dennisstritzke in https://github.com/RealOrangeOne/django-ta | Low | 6/8/2024 |
| 0.0.0 | Initial release :partying_face: This is just to get something out there, as opposed to something which is fully tested and working. At this time, the package should be considered "early alpha". | Low | 5/30/2024 |
