[![Package Testing](https://github.com/lukas346/django_firefly_tasks/actions/workflows/testing.yml/badge.svg)](https://github.com/lukas346/django_firefly_tasks/actions/workflows/testing.yml) [![PyPI version](https://badge.fury.io/py/django-firefly-tasks.svg)](https://badge.fury.io/py/django-firefly-tasks) [![PyPI Downloads](https://static.pepy.tech/badge/django-firefly-tasks)](https://pepy.tech/projects/django-firefly-tasks) # Introduction Simple and easy to use background tasks in Django without dependencies! ## Features * ⚔ **Easy background task creation** * šŸ›¤ļø **Multiple queue support** * šŸ”„ **Automatic task retrying** * šŸ› ļø **Well integrated with your chosen database** * 🚫 **No additional dependencies** * šŸ”€ **Supports both sync and async functions** ## Documentation [šŸ™‚ Click HERE ](https://lukas346.github.io/django_firefly_tasks/) ## Instalation ```bash pip install django_firefly_tasks ``` ## Setup settings.py ```python INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ############### 'django_firefly_tasks', ] LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'level': 'INFO', 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django_firefly_tasks': { 'handlers': ['console'], 'level': 'INFO', 'propagate': False, }, }, } ``` ## Quick Start **views.py** ```python from django.http.response import JsonResponse, Http404 from django_firefly_tasks.models import TaskModel from django_firefly_tasks.decorators import task from django_firefly_tasks.utils import task_as_dict @task(queue="default", max_retries=0, retry_delay=0) # param "queue" defines the queue in which the task will be placed # param "max_retries" defines max retries on fail # param "retry_delay" defines delay in seconds between restarts def add(i: int, j: int) -> int: return i + j def task_view(request): """ Example response --- { "id": 1, "func_name": "app.views.add", "status": "created", "not_before": null, "created": "2025-04-27T17:28:36.109Z", "retry_attempts": 0, "retry_delay": "0s", "max_retries": 0 } """ # pass function args to schedule method task = add.schedule(1, 3) return JsonResponse(task_as_dict(task)) def task_detail_view(request, task_id): """ Example response --- 4 """ try: task = TaskModel.objects.get(pk=task_id) except TaskModel.DoesNotExist: raise Http404("Task does not exist") # task.returned stores function returned data return JsonResponse(task.returned, safe=False) ``` **urls.py** ```python from django.urls import path from .views import task_view, task_detail_view urlpatterns = [ path('task/', task_view, name='task_view'), path('task/', task_detail_view, name='task_detail_view'), ] ``` Finally, run consumer. Default queue is called "default". **Consumer doesn't have auto-reload, so when tasks changed it requires manual restart.** ```bash ./manage.py consume_tasks ``` ## Frequently Asked Questions ### Consumer is too slow, what can I do? Set in your `settings.py` `CONSUMER_NAP_TIME` lower value (default `0.001` aka 1000 tasks per second). You can also try to scale it horizontally by defining multiple queues and running multiple consumers for each one. ### Can I run multiple consumers for the same queue? Yes, but it is not recommended. Consumers could lock each other. ## Support If this project was useful to you, [feel free to buy me a coffee ā˜•](https://www.paypal.com/donate/?hosted_button_id=Q7LLNBFFFY57Q). It doesn't have to be from Starbucks — even a budget one is just fine ;) Every donation, no matter how small, is a sign that what I’m doing is valuable to you and worth maintaining. [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/donate/?hosted_button_id=Q7LLNBFFFY57Q) ## Contact If you're missing something, feel free to add your own Issue or PR, which are, of course, welcome.