{"title":"Django’s Tasks framework","version":"dev","locale":"en","docname":"topics/tasks","url":"/en/dev/topics/tasks/","canonical":"https://djangodocs.dev/en/dev/topics/tasks/","summary":"For a web application, there’s often more than just turning HTTP requests into HTTP responses. For some functionality, it may be beneficial to run code outside the…","html":"<h1>Django’s Tasks framework<a class=\"heading-anchor\" href=\"#django-s-tasks-framework\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>For a web application, there’s often more than just turning HTTP requests into\nHTTP responses. For some functionality, it may be beneficial to run code\noutside the request-response cycle.</p>\n<p>That’s where background Tasks come in.</p>\n<p>Background Tasks can offload work to be run outside the request-response cycle,\nto be run elsewhere, potentially at a later date. This keeps requests fast,\nreduces latency, and improves the user experience. For example, a user\nshouldn’t have to wait for an email to send before their page finishes loading.</p>\n<p>Django’s Tasks framework makes it easy to define and enqueue such work. It\ndoes not provide a worker mechanism to run Tasks. The actual execution must be\nhandled by infrastructure outside Django, such as a separate process or\nservice. Given that, a <a class=\"reference internal\" href=\"#configuring-a-task-backend\"><span class=\"std std-ref\">task backend</span></a> capable\nof executing tasks on that service should be evaluated and configured.</p>\n<section id=\"background-task-fundamentals\">\n<h2>Background Task fundamentals<a class=\"heading-anchor\" href=\"#background-task-fundamentals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>When work needs to be done in the background, Django creates a <code class=\"docutils literal notranslate\"><span class=\"pre\">Task</span></code>, which\nis stored in the Queue Store. This <code class=\"docutils literal notranslate\"><span class=\"pre\">Task</span></code> contains all the metadata needed to\nexecute it, as well as a unique identifier for Django to retrieve the result\nlater.</p>\n<p>A Worker will look at the Queue Store for new Tasks to run. When a new Task is\nadded, a Worker claims the Task, executes it, and saves the status and result\nback to the Queue Store. These workers run outside the request-response\nlifecycle.</p>\n</section>\n<section id=\"configuring-a-task-backend\">\n<span id=\"id1\"></span><h2>Configuring a Task backend<a class=\"heading-anchor\" href=\"#configuring-a-task-backend\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>The Task backend determines how and where Tasks are stored for execution and\nhow they are executed. Different Task backends have different characteristics\nand configuration options, which may impact the performance and reliability of\nyour application. Django comes with <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#task-available-backends\"><span class=\"std std-ref\">built-in backends</span></a>, but these are for development and testing only.</p>\n<p>Django handles task definition, validation, queuing, and result handling, not\nexecution, so production setups need a backend or worker process that actually\nruns queued work. Relevant options are listed in the <a class=\"reference external\" href=\"https://www.djangoproject.com/community/ecosystem/\">Community Ecosystem</a> page.</p>\n<p>Task backends are configured using the <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-TASKS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TASKS</span></code></a> setting in your\nsettings file. Whilst most applications will only need a single backend,\nmultiple are supported.</p>\n<section id=\"immediate-execution\">\n<span id=\"immediate-task-backend\"></span><h3>Immediate execution<a class=\"heading-anchor\" href=\"#immediate-execution\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>This is the default backend if another is not specified in your settings file.\nThe <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.backends.immediate.ImmediateBackend\" title=\"django.tasks.backends.immediate.ImmediateBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ImmediateBackend</span></code></a> runs enqueued Tasks immediately, rather than in\nthe background. This allows background Task functionality to be slowly added to\nan application, before the required infrastructure is available.</p>\n<p>To use it, set <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-TASKS-BACKEND\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">BACKEND</span></code></a> to\n<code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;django.tasks.backends.immediate.ImmediateBackend&quot;</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">TASKS</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s2\">&quot;BACKEND&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.tasks.backends.immediate.ImmediateBackend&quot;</span><span class=\"p\">}}</span>\n</code></pre></div>\n<p>The <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.backends.immediate.ImmediateBackend\" title=\"django.tasks.backends.immediate.ImmediateBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ImmediateBackend</span></code></a> may also be useful in tests, to bypass the need\nto run a real background worker in your tests.</p>\n</section>\n<section id=\"dummy-backend\">\n<span id=\"dummy-task-backend\"></span><h3>Dummy backend<a class=\"heading-anchor\" href=\"#dummy-backend\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.backends.dummy.DummyBackend\" title=\"django.tasks.backends.dummy.DummyBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DummyBackend</span></code></a> doesn’t execute enqueued Tasks at all, instead\nstoring results for later use. Task results will forever remain in the\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.TaskResultStatus.READY\" title=\"django.tasks.TaskResultStatus.READY\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">READY</span></code></a> state.</p>\n<p>This backend is not intended for use in production - it is provided as a\nconvenience that can be used during development and testing.</p>\n<p>To use it, set <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-TASKS-BACKEND\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">BACKEND</span></code></a> to\n<code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;django.tasks.backends.dummy.DummyBackend&quot;</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">TASKS</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s2\">&quot;BACKEND&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.tasks.backends.dummy.DummyBackend&quot;</span><span class=\"p\">}}</span>\n</code></pre></div>\n<p>The results for enqueued Tasks can be retrieved from the backend’s\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.backends.dummy.DummyBackend.results\" title=\"django.tasks.backends.dummy.DummyBackend.results\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">results</span></code></a> attribute:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.tasks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">default_task_backend</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">my_task</span><span class=\"o\">.</span><span class=\"n\">enqueue</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">default_task_backend</span><span class=\"o\">.</span><span class=\"n\">results</span><span class=\"p\">)</span>\n<span class=\"go\">1</span>\n</code></pre></div>\n<p>Stored results can be cleared using the\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.backends.dummy.DummyBackend.clear\" title=\"django.tasks.backends.dummy.DummyBackend.clear\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">clear()</span></code></a> method:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">default_task_backend</span><span class=\"o\">.</span><span class=\"n\">clear</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">default_task_backend</span><span class=\"o\">.</span><span class=\"n\">results</span><span class=\"p\">)</span>\n<span class=\"go\">0</span>\n</code></pre></div>\n</section>\n<section id=\"third-party-backends\">\n<h3>Third-party backends<a class=\"heading-anchor\" href=\"#third-party-backends\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>As mentioned at the beginning of this section, Django includes backends\nsuitable for development and testing only. Production systems should rely on\nbackends that supply a worker process and a durable queue implementation.\nAvailable third-party backends are listed on the <a class=\"reference external\" href=\"https://www.djangoproject.com/community/ecosystem/#tasks\">Community Ecosystem page</a> and the <a class=\"reference external\" href=\"https://djangopackages.org/grids/g/task-framework/\">Tasks\nframework grid from Django Packages</a>.</p>\n<p>To use an external Task backend with Django, use the Python import path as the\n<a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-TASKS-BACKEND\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">BACKEND</span></code></a> of the <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-TASKS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TASKS</span></code></a> setting, like so:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">TASKS</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;BACKEND&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;path.to.backend&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>A Task backend is a class that inherits\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.backends.base.BaseTaskBackend\" title=\"django.tasks.backends.base.BaseTaskBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">BaseTaskBackend</span></code></a>. At a minimum, it must\nimplement <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.backends.base.BaseTaskBackend.enqueue\" title=\"django.tasks.backends.base.BaseTaskBackend.enqueue\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">BaseTaskBackend.enqueue()</span></code></a>. If you’re building your own\nbackend, you can use the built-in Task backends as reference implementations.\nYou’ll find the code in the <a class=\"extlink-source reference external\" href=\"https://github.com/django/django/blob/main/django/tasks/backends/\">django/tasks/backends/</a> directory of the\nDjango source.</p>\n</section>\n<section id=\"asynchronous-support\">\n<h3>Asynchronous support<a class=\"heading-anchor\" href=\"#asynchronous-support\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django has developing support for asynchronous Task backends.</p>\n<p><a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.backends.base.BaseTaskBackend\" title=\"django.tasks.backends.base.BaseTaskBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">BaseTaskBackend</span></code></a> has async variants of all\nbase methods. By convention, the asynchronous versions of all methods are\nprefixed with <code class=\"docutils literal notranslate\"><span class=\"pre\">a</span></code>. The arguments for both variants are the same.</p>\n</section>\n<section id=\"retrieving-backends\">\n<h3>Retrieving backends<a class=\"heading-anchor\" href=\"#retrieving-backends\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Backends can be retrieved using the <code class=\"docutils literal notranslate\"><span class=\"pre\">task_backends</span></code> connection handler:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.tasks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">task_backends</span>\n\n<span class=\"n\">task_backends</span><span class=\"p\">[</span><span class=\"s2\">&quot;default&quot;</span><span class=\"p\">]</span>  <span class=\"c1\"># The default backend</span>\n<span class=\"n\">task_backends</span><span class=\"p\">[</span><span class=\"s2\">&quot;reserve&quot;</span><span class=\"p\">]</span>  <span class=\"c1\"># Another backend</span>\n</code></pre></div>\n<p>The “default” backend is available as <code class=\"docutils literal notranslate\"><span class=\"pre\">default_task_backend</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.tasks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">default_task_backend</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"defining-tasks\">\n<span id=\"id2\"></span><h2>Defining Tasks<a class=\"heading-anchor\" href=\"#defining-tasks\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Tasks are defined using the <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.task\" title=\"django.tasks.task\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">django.tasks.task()</span></code></a> decorator on a\nmodule-level function:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.mail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">send_mail</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.tasks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">task</span>\n\n\n<span class=\"nd\">@task</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">email_users</span><span class=\"p\">(</span><span class=\"n\">emails</span><span class=\"p\">,</span> <span class=\"n\">subject</span><span class=\"p\">,</span> <span class=\"n\">message</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">send_mail</span><span class=\"p\">(</span>\n        <span class=\"n\">subject</span><span class=\"o\">=</span><span class=\"n\">subject</span><span class=\"p\">,</span> <span class=\"n\">message</span><span class=\"o\">=</span><span class=\"n\">message</span><span class=\"p\">,</span> <span class=\"n\">from_email</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"n\">recipient_list</span><span class=\"o\">=</span><span class=\"n\">emails</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n<p>The return value of the decorator is a <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task\" title=\"django.tasks.Task\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Task</span></code></a> instance.</p>\n<p><a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task\" title=\"django.tasks.Task\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Task</span></code></a> attributes can be customized via the <code class=\"docutils literal notranslate\"><span class=\"pre\">&#64;task</span></code>\ndecorator arguments:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.mail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">send_mail</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.tasks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">task</span>\n\n\n<span class=\"nd\">@task</span><span class=\"p\">(</span><span class=\"n\">priority</span><span class=\"o\">=</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"n\">queue_name</span><span class=\"o\">=</span><span class=\"s2\">&quot;emails&quot;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">email_users</span><span class=\"p\">(</span><span class=\"n\">emails</span><span class=\"p\">,</span> <span class=\"n\">subject</span><span class=\"p\">,</span> <span class=\"n\">message</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">send_mail</span><span class=\"p\">(</span>\n        <span class=\"n\">subject</span><span class=\"o\">=</span><span class=\"n\">subject</span><span class=\"p\">,</span> <span class=\"n\">message</span><span class=\"o\">=</span><span class=\"n\">message</span><span class=\"p\">,</span> <span class=\"n\">from_email</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"n\">recipient_list</span><span class=\"o\">=</span><span class=\"n\">emails</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n<p>By convention, Tasks are defined in a <code class=\"docutils literal notranslate\"><span class=\"pre\">tasks.py</span></code> file, however this is not\nenforced.</p>\n<section id=\"task-context\">\n<span id=\"id3\"></span><h3>Task context<a class=\"heading-anchor\" href=\"#task-context\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Sometimes, the running <code class=\"docutils literal notranslate\"><span class=\"pre\">Task</span></code> may need to know context about how it was\nenqueued, and how it is being executed. This can be accessed by taking a\n<code class=\"docutils literal notranslate\"><span class=\"pre\">context</span></code> argument, which is an instance of\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.TaskContext\" title=\"django.tasks.TaskContext\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TaskContext</span></code></a>.</p>\n<p>To receive the Task context as an argument to your Task function, pass\n<code class=\"docutils literal notranslate\"><span class=\"pre\">takes_context</span></code> when defining it:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">logging</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.mail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">send_mail</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.tasks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">task</span>\n\n<span class=\"n\">logger</span> <span class=\"o\">=</span> <span class=\"n\">logging</span><span class=\"o\">.</span><span class=\"n\">getLogger</span><span class=\"p\">(</span><span class=\"vm\">__name__</span><span class=\"p\">)</span>\n\n\n<span class=\"nd\">@task</span><span class=\"p\">(</span><span class=\"n\">takes_context</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">email_users</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"n\">emails</span><span class=\"p\">,</span> <span class=\"n\">subject</span><span class=\"p\">,</span> <span class=\"n\">message</span><span class=\"p\">):</span>\n    <span class=\"n\">logger</span><span class=\"o\">.</span><span class=\"n\">debug</span><span class=\"p\">(</span>\n        <span class=\"sa\">f</span><span class=\"s2\">&quot;Attempt </span><span class=\"si\">{</span><span class=\"n\">context</span><span class=\"o\">.</span><span class=\"n\">attempt</span><span class=\"si\">}</span><span class=\"s2\"> to send user email. Task result id: </span><span class=\"si\">{</span><span class=\"n\">context</span><span class=\"o\">.</span><span class=\"n\">task_result</span><span class=\"o\">.</span><span class=\"n\">id</span><span class=\"si\">}</span><span class=\"s2\">.&quot;</span>\n    <span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">send_mail</span><span class=\"p\">(</span>\n        <span class=\"n\">subject</span><span class=\"o\">=</span><span class=\"n\">subject</span><span class=\"p\">,</span> <span class=\"n\">message</span><span class=\"o\">=</span><span class=\"n\">message</span><span class=\"p\">,</span> <span class=\"n\">from_email</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"n\">recipient_list</span><span class=\"o\">=</span><span class=\"n\">emails</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"modifying-tasks\">\n<span id=\"id4\"></span><h3>Modifying Tasks<a class=\"heading-anchor\" href=\"#modifying-tasks\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Before enqueueing Tasks, it may be necessary to modify certain parameters of\nthe Task. For example, to give it a higher priority than it would normally.</p>\n<p>A <code class=\"docutils literal notranslate\"><span class=\"pre\">Task</span></code> instance cannot be modified directly. Instead, a modified instance\ncan be created with the <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task.using\" title=\"django.tasks.Task.using\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">using()</span></code></a> method, leaving the\noriginal as-is. For example:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">email_users</span><span class=\"o\">.</span><span class=\"n\">priority</span>\n<span class=\"go\">0</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">email_users</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">(</span><span class=\"n\">priority</span><span class=\"o\">=</span><span class=\"mi\">10</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">priority</span>\n<span class=\"go\">10</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"enqueueing-tasks\">\n<span id=\"id5\"></span><h2>Enqueueing Tasks<a class=\"heading-anchor\" href=\"#enqueueing-tasks\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>To add the Task to the queue store, so it will be executed, call the\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task.enqueue\" title=\"django.tasks.Task.enqueue\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">enqueue()</span></code></a> method on it. If the Task takes arguments,\nthese can be passed as-is. For example:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">result</span> <span class=\"o\">=</span> <span class=\"n\">email_users</span><span class=\"o\">.</span><span class=\"n\">enqueue</span><span class=\"p\">(</span>\n    <span class=\"n\">emails</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;user@example.com&quot;</span><span class=\"p\">],</span>\n    <span class=\"n\">subject</span><span class=\"o\">=</span><span class=\"s2\">&quot;You have a message&quot;</span><span class=\"p\">,</span>\n    <span class=\"n\">message</span><span class=\"o\">=</span><span class=\"s2\">&quot;Hello there!&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>This returns a <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.TaskResult\" title=\"django.tasks.TaskResult\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TaskResult</span></code></a>, which can be used to retrieve\nthe result of the Task once it has finished executing.</p>\n<p>To enqueue Tasks in an <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span></code> context, <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task.aenqueue\" title=\"django.tasks.Task.aenqueue\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">aenqueue()</span></code></a>\nis available as an <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span></code> variant of <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task.enqueue\" title=\"django.tasks.Task.enqueue\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">enqueue()</span></code></a>.</p>\n<p>Because both Task arguments and return values are serialized to JSON, they must\nbe JSON-serializable:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">process_data</span><span class=\"o\">.</span><span class=\"n\">enqueue</span><span class=\"p\">(</span><span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">())</span>\n<span class=\"gt\">Traceback (most recent call last):</span>\n<span class=\"c\">...</span>\n<span class=\"gr\">TypeError</span>: <span class=\"n\">Object of type datetime is not JSON serializable</span>\n</code></pre></div>\n<p>Arguments must also be able to round-trip through a <a class=\"reference external\" href=\"https://docs.python.org/3/library/json.html#json.dumps\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">json.dumps()</span></code></a>/\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/json.html#json.loads\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">json.loads()</span></code></a> cycle without changing type. For example, consider this\nTask:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@task</span><span class=\"p\">()</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">double_dictionary</span><span class=\"p\">(</span><span class=\"n\">key</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"p\">{</span><span class=\"n\">key</span><span class=\"p\">:</span> <span class=\"n\">key</span> <span class=\"o\">*</span> <span class=\"mi\">2</span><span class=\"p\">}</span>\n</code></pre></div>\n<p>With the <code class=\"docutils literal notranslate\"><span class=\"pre\">ImmediateBackend</span></code> configured as the default backend:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span> <span class=\"o\">=</span> <span class=\"n\">double_dictionary</span><span class=\"o\">.</span><span class=\"n\">enqueue</span><span class=\"p\">((</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">3</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">status</span>\n<span class=\"go\">FAILED</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">errors</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">traceback</span>\n<span class=\"gt\">Traceback (most recent call last):</span>\n<span class=\"c\">...</span>\n<span class=\"gr\">TypeError</span>: <span class=\"n\">unhashable type: &#39;list&#39;</span>\n</code></pre></div>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">double_dictionary</span></code> Task fails because after the JSON round-trip the\ntuple <code class=\"docutils literal notranslate\"><span class=\"pre\">(1,</span> <span class=\"pre\">2,</span> <span class=\"pre\">3)</span></code> becomes the list <code class=\"docutils literal notranslate\"><span class=\"pre\">[1,</span> <span class=\"pre\">2,</span> <span class=\"pre\">3]</span></code>, which cannot be used as a\ndictionary key.</p>\n<p>In general, complex objects such as model instances, or built-in types like\n<code class=\"docutils literal notranslate\"><span class=\"pre\">datetime</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">tuple</span></code> cannot be used in Tasks without additional\nconversion.</p>\n<section id=\"transactions\">\n<span id=\"task-transactions\"></span><h3>Transactions<a class=\"heading-anchor\" href=\"#transactions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>For most backends, Tasks are run in a separate process, using a different\ndatabase connection. When using a transaction, without waiting for it to\ncommit, workers could start to process a Task which uses objects it can’t\naccess yet.</p>\n<p>For example, consider this simplified example:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@task</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_task</span><span class=\"p\">(</span><span class=\"n\">thing_num</span><span class=\"p\">):</span>\n    <span class=\"n\">Thing</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">num</span><span class=\"o\">=</span><span class=\"n\">thing_num</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>\n    <span class=\"n\">Thing</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">num</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n    <span class=\"n\">my_task</span><span class=\"o\">.</span><span class=\"n\">enqueue</span><span class=\"p\">(</span><span class=\"n\">thing_num</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>To prevent the scenario where <code class=\"docutils literal notranslate\"><span class=\"pre\">my_task</span></code> runs before the <code class=\"docutils literal notranslate\"><span class=\"pre\">Thing</span></code> is\ncommitted to the database, use <a class=\"reference internal\" href=\"/en/dev/topics/db/transactions/#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">transaction.on_commit()</span></code></a>, binding all arguments to\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task.enqueue\" title=\"django.tasks.Task.enqueue\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">enqueue()</span></code></a> via <a class=\"reference external\" href=\"https://docs.python.org/3/library/functools.html#functools.partial\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">functools.partial()</span></code></a>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">functools</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">partial</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">transaction</span>\n\n<span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>\n    <span class=\"n\">Thing</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">num</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">partial</span><span class=\"p\">(</span><span class=\"n\">my_task</span><span class=\"o\">.</span><span class=\"n\">enqueue</span><span class=\"p\">,</span> <span class=\"n\">thing_num</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">))</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"task-results\">\n<span id=\"id6\"></span><h2>Task results<a class=\"heading-anchor\" href=\"#task-results\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>When enqueueing a <code class=\"docutils literal notranslate\"><span class=\"pre\">Task</span></code>, you receive a <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.TaskResult\" title=\"django.tasks.TaskResult\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TaskResult</span></code></a>,\nhowever it’s likely useful to retrieve the result from somewhere else (for\nexample another request or another Task).</p>\n<p>Each <code class=\"docutils literal notranslate\"><span class=\"pre\">TaskResult</span></code> has a unique <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.TaskResult.id\" title=\"django.tasks.TaskResult.id\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">id</span></code></a>, which can\nbe used to identify and retrieve the result once the code which enqueued the\nTask has finished.</p>\n<p>The <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task.get_result\" title=\"django.tasks.Task.get_result\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_result()</span></code></a> method can retrieve a result based on\nits <code class=\"docutils literal notranslate\"><span class=\"pre\">id</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"c1\"># Later, somewhere else...</span>\n<span class=\"n\">result</span> <span class=\"o\">=</span> <span class=\"n\">email_users</span><span class=\"o\">.</span><span class=\"n\">get_result</span><span class=\"p\">(</span><span class=\"n\">result_id</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>To retrieve a <code class=\"docutils literal notranslate\"><span class=\"pre\">TaskResult</span></code>, regardless of which kind of <code class=\"docutils literal notranslate\"><span class=\"pre\">Task</span></code> it was from,\nuse the <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task.get_result\" title=\"django.tasks.Task.get_result\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_result()</span></code></a> method on the backend:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.tasks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">default_task_backend</span>\n\n<span class=\"n\">result</span> <span class=\"o\">=</span> <span class=\"n\">default_task_backend</span><span class=\"o\">.</span><span class=\"n\">get_result</span><span class=\"p\">(</span><span class=\"n\">result_id</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>To retrieve results in an <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span></code> context,\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task.aget_result\" title=\"django.tasks.Task.aget_result\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">aget_result()</span></code></a> is available as an <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span></code> variant of\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task.get_result\" title=\"django.tasks.Task.get_result\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_result()</span></code></a> on both the backend and <code class=\"docutils literal notranslate\"><span class=\"pre\">Task</span></code>.</p>\n<p>Some backends, such as the built-in <code class=\"docutils literal notranslate\"><span class=\"pre\">ImmediateBackend</span></code> do not support\n<code class=\"docutils literal notranslate\"><span class=\"pre\">get_result()</span></code>. Calling <code class=\"docutils literal notranslate\"><span class=\"pre\">get_result()</span></code> on these backends will\nraise <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#NotImplementedError\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">NotImplementedError</span></code></a>.</p>\n<section id=\"updating-results\">\n<h3>Updating results<a class=\"heading-anchor\" href=\"#updating-results\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>A <code class=\"docutils literal notranslate\"><span class=\"pre\">TaskResult</span></code> contains the status of a Task’s execution at the point it was\nretrieved. If the Task finishes after <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.Task.get_result\" title=\"django.tasks.Task.get_result\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_result()</span></code></a> is\ncalled, it will not update.</p>\n<p>To refresh the values, call the <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.TaskResult.refresh\" title=\"django.tasks.TaskResult.refresh\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">django.tasks.TaskResult.refresh()</span></code></a>\nmethod:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">status</span>\n<span class=\"go\">RUNNING</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">refresh</span><span class=\"p\">()</span>  <span class=\"c1\"># or await result.arefresh()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">status</span>\n<span class=\"go\">SUCCESSFUL</span>\n</code></pre></div>\n</section>\n<section id=\"return-values\">\n<span id=\"task-return-values\"></span><h3>Return values<a class=\"heading-anchor\" href=\"#return-values\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>If your Task function returns something, it can be retrieved from the\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.TaskResult.return_value\" title=\"django.tasks.TaskResult.return_value\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">django.tasks.TaskResult.return_value</span></code></a> attribute:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">status</span>\n<span class=\"go\">SUCCESSFUL</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">return_value</span>\n<span class=\"go\">42</span>\n</code></pre></div>\n<p>If the Task has not finished executing, or has failed, <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#ValueError\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ValueError</span></code></a> is\nraised.</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">status</span>\n<span class=\"go\">RUNNING</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">return_value</span>\n<span class=\"gt\">Traceback (most recent call last):</span>\n<span class=\"c\">...</span>\n<span class=\"gr\">ValueError</span>: <span class=\"n\">Task has not finished yet</span>\n</code></pre></div>\n</section>\n<section id=\"errors\">\n<h3>Errors<a class=\"heading-anchor\" href=\"#errors\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>If the Task doesn’t succeed, and instead raises an exception, either as part of\nthe Task or as part of running it, the exception and traceback are saved to the\n<a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.TaskResult.errors\" title=\"django.tasks.TaskResult.errors\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">django.tasks.TaskResult.errors</span></code></a> list.</p>\n<p>Each entry in <code class=\"docutils literal notranslate\"><span class=\"pre\">errors</span></code> is a <a class=\"reference internal\" href=\"/en/dev/ref/tasks/#django.tasks.TaskError\" title=\"django.tasks.TaskError\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TaskError</span></code></a> containing\ninformation about error raised during the execution:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">errors</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">exception_class</span>\n<span class=\"go\">&lt;class &#39;ValueError&#39;&gt;</span>\n</code></pre></div>\n<p>Note that this is just the type of exception, and contains no other values. The\ntraceback information is reduced to a string which you can use to help\ndebugging:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">errors</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">traceback</span>\n<span class=\"gt\">Traceback (most recent call last):</span>\n<span class=\"c\">...</span>\n<span class=\"gr\">TypeError</span>: <span class=\"n\">Object of type datetime is not JSON serializable</span>\n</code></pre></div>\n</section>\n</section>","rootId":"django-s-tasks-framework","toc":[{"title":"Background Task fundamentals","anchor":"background-task-fundamentals","children":[]},{"title":"Configuring a Task backend","anchor":"configuring-a-task-backend","children":[{"title":"Immediate execution","anchor":"immediate-execution","children":[]},{"title":"Dummy backend","anchor":"dummy-backend","children":[]},{"title":"Third-party backends","anchor":"third-party-backends","children":[]},{"title":"Asynchronous support","anchor":"asynchronous-support","children":[]},{"title":"Retrieving backends","anchor":"retrieving-backends","children":[]}]},{"title":"Defining Tasks","anchor":"defining-tasks","children":[{"title":"Task context","anchor":"task-context","children":[]},{"title":"Modifying Tasks","anchor":"modifying-tasks","children":[]}]},{"title":"Enqueueing Tasks","anchor":"enqueueing-tasks","children":[{"title":"Transactions","anchor":"transactions","children":[]}]},{"title":"Task results","anchor":"task-results","children":[{"title":"Updating results","anchor":"updating-results","children":[]},{"title":"Return values","anchor":"return-values","children":[]},{"title":"Errors","anchor":"errors","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Using Django","url":"/en/dev/topics/"}],"prev":{"docname":"topics/async","title":"Asynchronous support","url":"/en/dev/topics/async/"},"next":{"docname":"howto/index","title":"How-to guides","url":"/en/dev/howto/"},"formats":{"html":"/en/dev/topics/tasks/","markdown":"/en/dev/topics/tasks.md","json":"/en/dev/topics/tasks.json"},"source":"https://github.com/django/django/blob/main/docs/topics/tasks.txt","official":"https://docs.djangoproject.com/en/dev/topics/tasks/","inVersions":["dev","6.1","6.0"],"inLocales":["en"]}