Skip to content

Commit 33562b8

Browse files
krtko1codingjoe
andauthored
Resolve #122 -- Add Django-RQ support for async image processing (#124)
Co-authored-by: Johannes Maron <[email protected]>
1 parent 40ce71a commit 33562b8

File tree

7 files changed

+72
-6
lines changed

7 files changed

+72
-6
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ jobs:
129129
extras:
130130
- "celery"
131131
- "dramatiq"
132+
- "django-rq"
132133
- "drf"
133134
- "cleanup"
134135
runs-on: ubuntu-latest
@@ -139,8 +140,8 @@ jobs:
139140
with:
140141
python-version: 3.x
141142
- name: Install redis
142-
if: matrix.extras == 'dramatiq'
143-
run: sudo apt-get install -y redis-server
143+
if: matrix.extras == 'dramatiq' || matrix.extras == 'django-rq'
144+
run: sudo apt install -y redis-server
144145
- run: python -m pip install .[test,${{ matrix.extras }}]
145146
- run: python -m pytest
146147
- uses: codecov/codecov-action@v3

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Responsive cross-browser image library using modern codes like AVIF & WebP.
99
* serve files with or without a CDN
1010
* placeholders for local development
1111
* migration support
12-
* async image processing for [Celery] or [Dramatiq]
12+
* async image processing for [Celery], [Dramatiq] or [Django RQ][django-rq]
1313
* [DRF] support
1414

1515
[![PyPi Version](https://img.shields.io/pypi/v/django-pictures.svg)](https://pypi.python.org/pypi/django-pictures/)
@@ -287,3 +287,4 @@ which automatically deletes its file and corresponding `SimplePicture` files.
287287
[drf]: https://www.django-rest-framework.org/
288288
[celery]: https://docs.celeryproject.org/en/stable/
289289
[dramatiq]: https://dramatiq.io/
290+
[django-rq]: https://github.com/rq/django-rq

pictures/tasks.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,30 @@ def process_picture(field_file: PictureFieldFile) -> None: # noqa: F811
112112
queue=conf.get_settings().QUEUE_NAME,
113113
)
114114
)
115+
116+
117+
try:
118+
from django_rq import job
119+
except ImportError:
120+
pass
121+
else:
122+
123+
@job(conf.get_settings().QUEUE_NAME)
124+
def process_picture_with_django_rq(
125+
app_name, model_name, field_name, file_name, storage_construct
126+
) -> None:
127+
process_picture_async(
128+
app_name, model_name, field_name, file_name, storage_construct
129+
)
130+
131+
def process_picture(field_file: PictureFieldFile) -> None: # noqa: F811
132+
opts = field_file.instance._meta
133+
transaction.on_commit(
134+
lambda: process_picture_with_django_rq.delay(
135+
app_name=opts.app_label,
136+
model_name=opts.model_name,
137+
field_name=field_file.field.name,
138+
file_name=field_file.name,
139+
storage_construct=field_file.storage.deconstruct(),
140+
)
141+
)

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ dramatiq = [
4949
celery = [
5050
"celery",
5151
]
52+
django-rq = [
53+
"django-rq",
54+
]
5255
drf = [
5356
"djangorestframework",
5457
]

tests/conftest.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,19 @@ def stub_worker():
3232
try:
3333
import dramatiq
3434
except ImportError:
35-
yield Mock()
35+
try:
36+
from django_rq import get_worker
37+
except ImportError:
38+
yield Mock()
39+
else:
40+
41+
class Meta:
42+
@staticmethod
43+
def join():
44+
get_worker("pictures").work(burst=True)
45+
46+
yield Meta
47+
3648
else:
3749
broker = dramatiq.get_broker()
3850
broker.emit_after("process_boot")

tests/test_migrations.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,14 @@
1919
except ImportError:
2020
celery = None
2121

22+
try:
23+
import django_rq
24+
except ImportError:
25+
django_rq = None
2226

2327
skip_dramatiq = pytest.mark.skipif(
24-
not all(x is None for x in [dramatiq, celery]),
25-
reason="dramatiq and celery are installed",
28+
not all(x is None for x in [dramatiq, celery, django_rq]),
29+
reason="dramatiq, celery and django-rq are installed",
2630
)
2731

2832

tests/testapp/settings.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,21 @@
162162

163163
CELERY_BROKER_URL = "redis:///2"
164164
CELERY_TASK_ALWAYS_EAGER = True
165+
166+
# django-rq
167+
try:
168+
import django_rq # NoQA
169+
except ImportError: # django_rq is not installed
170+
pass
171+
else:
172+
INSTALLED_APPS += ["django_rq"]
173+
174+
RQ_QUEUES = {
175+
"pictures": {
176+
"URL": os.getenv("REDIS_URL", "redis:///3"),
177+
}
178+
}
179+
180+
RQ = {
181+
"WORKER_CLASS": "rq.worker.SimpleWorker",
182+
}

0 commit comments

Comments
 (0)