Skip to content

Commit 786ca25

Browse files
viv1brendawelesbzaczynski
authored
Sample code for the article on Django tasks (#768)
* Sample code for the article on Django Tasks * code style and formatting fixes * update import location * Update README.md --------- Co-authored-by: brendaweles <160772586+brendaweles@users.noreply.github.com> Co-authored-by: Bartosz Zaczyński <bartosz.zaczynski@gmail.com>
1 parent aa7d0dd commit 786ca25

14 files changed

Lines changed: 272 additions & 0 deletions

File tree

django-tasks/README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Django Tasks: Exploring the Built-in Tasks Framework
2+
3+
Example project for the Real Python tutorial [Django Tasks: Exploring the Built-in Tasks Framework](https://realpython.com/django-tasks/).
4+
5+
The project demonstrates Django 6's `@task` decorator, the `django-tasks-db` database-backed worker, named queues with priorities, and the `transaction.on_commit` pattern for safe enqueueing inside an atomic block.
6+
7+
## Setup
8+
9+
Set up a virtual environment and install dependencies:
10+
11+
```sh
12+
$ python -m venv venv
13+
$ source venv/bin/activate
14+
(venv) $ python -m pip install -r requirements.txt
15+
```
16+
17+
Run migrations:
18+
19+
```sh
20+
(venv) $ python -m manage makemigrations myapp
21+
(venv) $ python -m manage migrate
22+
```
23+
24+
## Run
25+
26+
The project uses two processes: the Django dev server and the `db_worker`.
27+
28+
In one terminal, start the worker:
29+
30+
```sh
31+
(venv) $ python -m manage db_worker --queue-name '*'
32+
```
33+
34+
In a second terminal, start the dev server:
35+
36+
```sh
37+
(venv) $ python -m manage runserver
38+
```
39+
40+
Trigger the demo endpoints with `curl` or your browser:
41+
42+
```sh
43+
$ curl 'http://localhost:8000/register/?email=alice@example.com&name=Alice'
44+
$ curl http://localhost:8000/checkout/
45+
$ curl http://localhost:8000/task-status/<task-id>/
46+
```
47+
48+
You can also enqueue tasks from the Django shell:
49+
50+
```sh
51+
(venv) $ python -m manage shell
52+
```
53+
54+
```pycon
55+
>>> from myapp.tasks import say_hello
56+
>>> result = say_hello.enqueue("Real Python")
57+
>>> result.refresh()
58+
>>> result.status
59+
SUCCESSFUL
60+
>>> result.return_value
61+
'Hello, Real Python!'
62+
```

django-tasks/config/__init__.py

Whitespace-only changes.

django-tasks/config/settings.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from pathlib import Path
2+
3+
BASE_DIR = Path(__file__).resolve().parent.parent
4+
5+
SECRET_KEY = "django-insecure-demo-key-do-not-use-in-production"
6+
DEBUG = True
7+
ALLOWED_HOSTS = ["*"]
8+
9+
INSTALLED_APPS = [
10+
"django.contrib.contenttypes",
11+
"django.contrib.auth",
12+
"django_tasks_db",
13+
"myapp",
14+
]
15+
16+
MIDDLEWARE = []
17+
18+
ROOT_URLCONF = "config.urls"
19+
20+
DATABASES = {
21+
"default": {
22+
"ENGINE": "django.db.backends.sqlite3",
23+
"NAME": BASE_DIR / "db.sqlite3",
24+
}
25+
}
26+
27+
TASKS = {
28+
"default": {
29+
"BACKEND": "django_tasks_db.DatabaseBackend",
30+
"QUEUES": ["default", "emails", "reports"],
31+
},
32+
}
33+
34+
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
35+
DEFAULT_FROM_EMAIL = "noreply@example.com"
36+
37+
USE_TZ = True
38+
TIME_ZONE = "UTC"
39+
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

django-tasks/config/urls.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from django.urls import include, path
2+
3+
urlpatterns = [
4+
path("", include("myapp.urls")),
5+
]

django-tasks/manage.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env python
2+
"""Django's command-line utility for administrative tasks."""
3+
4+
import os
5+
import sys
6+
7+
8+
def main():
9+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
10+
try:
11+
from django.core.management import execute_from_command_line
12+
except ImportError as exc:
13+
raise ImportError(
14+
"Couldn't import Django. Are you sure it's installed and "
15+
"available on your PYTHONPATH environment variable? Did you "
16+
"forget to activate a virtual environment?"
17+
) from exc
18+
execute_from_command_line(sys.argv)
19+
20+
21+
if __name__ == "__main__":
22+
main()

django-tasks/myapp/__init__.py

Whitespace-only changes.

django-tasks/myapp/apps.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class MyappConfig(AppConfig):
5+
default_auto_field = "django.db.models.BigAutoField"
6+
name = "myapp"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Generated by Django 6.0.3 on 2026-05-03 11:08
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
initial = True
9+
10+
dependencies = []
11+
12+
operations = [
13+
migrations.CreateModel(
14+
name="Order",
15+
fields=[
16+
(
17+
"id",
18+
models.BigAutoField(
19+
auto_created=True,
20+
primary_key=True,
21+
serialize=False,
22+
verbose_name="ID",
23+
),
24+
),
25+
("item", models.CharField(default="widget", max_length=100)),
26+
("created_at", models.DateTimeField(auto_now_add=True)),
27+
],
28+
),
29+
migrations.CreateModel(
30+
name="User",
31+
fields=[
32+
(
33+
"id",
34+
models.BigAutoField(
35+
auto_created=True,
36+
primary_key=True,
37+
serialize=False,
38+
verbose_name="ID",
39+
),
40+
),
41+
("email", models.EmailField(max_length=254)),
42+
("name", models.CharField(blank=True, max_length=100)),
43+
],
44+
),
45+
]

django-tasks/myapp/migrations/__init__.py

Whitespace-only changes.

django-tasks/myapp/models.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from django.db import models
2+
3+
4+
class User(models.Model):
5+
email = models.EmailField()
6+
name = models.CharField(max_length=100, blank=True)
7+
8+
def __str__(self):
9+
return self.email
10+
11+
12+
class Order(models.Model):
13+
item = models.CharField(max_length=100, default="widget")
14+
created_at = models.DateTimeField(auto_now_add=True)
15+
16+
def __str__(self):
17+
return f"Order {self.pk} ({self.item})"

0 commit comments

Comments
 (0)