Skip to content

Commit 38cdf0d

Browse files
authored
Merge pull request #273 from realpython/celery-async-email
Celery async tasks - sending emails
2 parents 5a1d5f8 + 6c4ec93 commit 38cdf0d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+742
-0
lines changed

celery-async-tasks/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Asynchronous Tasks with Django and Celery
2+
3+
Example project for integrating Celery and Redis into a Django application.
4+
This repository holds the code for the Real Python [Asynchronous Tasks With Django and Celery](https://realpython.com/asynchronous-tasks-with-django-and-celery/) tutorial.
5+
6+
## Setup (macOS)
7+
8+
To try the project, set up a virtual environment and install the listed dependencies:
9+
10+
```sh
11+
$ python -m venv venv
12+
$ source venv/bin/activate
13+
(venv) $ python -m pip install -r requirements.txt
14+
```
15+
16+
You'll also need to install Redis on your system:
17+
18+
```sh
19+
$ brew install redis
20+
```
21+
22+
Once you've installed all the dependencies, you need to start three processes that need to run at the same time:
23+
24+
1. Django
25+
2. Redis
26+
3. Celery
27+
28+
To get all of them running, open three different terminal windows and start them one-by-one:
29+
30+
**Django app:**
31+
32+
```sh
33+
(venv) $ python manage.py migrate
34+
(venv) $ python manage.py runserver
35+
```
36+
37+
**Redis server:**
38+
39+
```sh
40+
$ redis-server
41+
```
42+
43+
**Celery:**
44+
45+
```sh
46+
(venv) $ python -m celery -A django_celery worker -l info
47+
```
48+
49+
When all three processes are running, you can go to `localhost:8000/` and submit a feedback response. Celery will simulate a work-intensive process and send an email at the end of it. You'll see the email message show up in the log stream on the terminal window where the Celery worker is running.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dump.rdb
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .celery import app as celery_app
2+
3+
__all__ = ("celery_app",)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
ASGI config for django_celery project.
3+
4+
It exposes the ASGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
8+
"""
9+
10+
import os
11+
12+
from django.core.asgi import get_asgi_application
13+
14+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_celery.settings")
15+
16+
application = get_asgi_application()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import os
2+
3+
from celery import Celery
4+
5+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_celery.settings")
6+
app = Celery("django_celery")
7+
app.config_from_object("django.conf:settings", namespace="CELERY")
8+
app.autodiscover_tasks()
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
"""
2+
Django settings for django_celery project.
3+
4+
Generated by 'django-admin startproject' using Django 4.0.6.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/4.0/topics/settings/
8+
9+
For the full list of settings and their values, see
10+
https://docs.djangoproject.com/en/4.0/ref/settings/
11+
"""
12+
13+
from pathlib import Path
14+
15+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
16+
BASE_DIR = Path(__file__).resolve().parent.parent
17+
18+
19+
# Quick-start development settings - unsuitable for production
20+
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
21+
22+
# SECURITY WARNING: keep the secret key used in production secret!
23+
SECRET_KEY = (
24+
"django-insecure-26w#-h7$d@obw2g^r%&!$6cs4s+3^strd^ky8-3wb90*lg8e_i"
25+
)
26+
27+
# SECURITY WARNING: don't run with debug turned on in production!
28+
DEBUG = True
29+
30+
ALLOWED_HOSTS = []
31+
32+
33+
# Application definition
34+
35+
INSTALLED_APPS = [
36+
"django.contrib.admin",
37+
"django.contrib.auth",
38+
"django.contrib.contenttypes",
39+
"django.contrib.sessions",
40+
"django.contrib.messages",
41+
"django.contrib.staticfiles",
42+
"feedback.apps.FeedbackConfig",
43+
]
44+
45+
MIDDLEWARE = [
46+
"django.middleware.security.SecurityMiddleware",
47+
"django.contrib.sessions.middleware.SessionMiddleware",
48+
"django.middleware.common.CommonMiddleware",
49+
"django.middleware.csrf.CsrfViewMiddleware",
50+
"django.contrib.auth.middleware.AuthenticationMiddleware",
51+
"django.contrib.messages.middleware.MessageMiddleware",
52+
"django.middleware.clickjacking.XFrameOptionsMiddleware",
53+
]
54+
55+
ROOT_URLCONF = "django_celery.urls"
56+
57+
TEMPLATES = [
58+
{
59+
"BACKEND": "django.template.backends.django.DjangoTemplates",
60+
"DIRS": [],
61+
"APP_DIRS": True,
62+
"OPTIONS": {
63+
"context_processors": [
64+
"django.template.context_processors.debug",
65+
"django.template.context_processors.request",
66+
"django.contrib.auth.context_processors.auth",
67+
"django.contrib.messages.context_processors.messages",
68+
],
69+
},
70+
},
71+
]
72+
73+
WSGI_APPLICATION = "django_celery.wsgi.application"
74+
75+
76+
# Database
77+
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
78+
79+
DATABASES = {
80+
"default": {
81+
"ENGINE": "django.db.backends.sqlite3",
82+
"NAME": BASE_DIR / "db.sqlite3",
83+
}
84+
}
85+
86+
87+
# Password validation
88+
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
89+
90+
AUTH_PASSWORD_VALIDATORS = [
91+
{
92+
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
93+
},
94+
{
95+
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
96+
},
97+
{
98+
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
99+
},
100+
{
101+
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
102+
},
103+
]
104+
105+
106+
# Internationalization
107+
# https://docs.djangoproject.com/en/4.0/topics/i18n/
108+
109+
LANGUAGE_CODE = "en-us"
110+
111+
TIME_ZONE = "UTC"
112+
113+
USE_I18N = True
114+
115+
USE_TZ = True
116+
117+
118+
# Static files (CSS, JavaScript, Images)
119+
# https://docs.djangoproject.com/en/4.0/howto/static-files/
120+
121+
STATIC_URL = "static/"
122+
123+
# Default primary key field type
124+
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
125+
126+
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
127+
128+
# Email placeholder setting
129+
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
130+
131+
# Celery settings
132+
CELERY_BROKER_URL = "redis://localhost:6379"
133+
CELERY_RESULT_BACKEND = "redis://localhost:6379"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""django_celery URL Configuration
2+
3+
The `urlpatterns` list routes URLs to views. For more information please see:
4+
https://docs.djangoproject.com/en/4.0/topics/http/urls/
5+
Examples:
6+
Function views
7+
1. Add an import: from my_app import views
8+
2. Add a URL to urlpatterns: path('', views.home, name='home')
9+
Class-based views
10+
1. Add an import: from other_app.views import Home
11+
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12+
Including another URLconf
13+
1. Import the include() function: from django.urls import include, path
14+
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15+
"""
16+
from django.contrib import admin
17+
from django.urls import include, path
18+
19+
urlpatterns = [
20+
path("admin/", admin.site.urls),
21+
path("", include("feedback.urls")),
22+
]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
WSGI config for django_celery project.
3+
4+
It exposes the WSGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/
8+
"""
9+
10+
import os
11+
12+
from django.core.wsgi import get_wsgi_application
13+
14+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_celery.settings")
15+
16+
application = get_wsgi_application()

celery-async-tasks/source_code_final/feedback/__init__.py

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# from django.contrib import admin
2+
3+
# Register your models here.

0 commit comments

Comments
 (0)