Use Celery to make pdf from HTML page

 Why Use Celery in Django? A Complete Guide to Installing and Using Celery 🚀

celery-project


Django is a powerful web framework for building scalable applications, but what if you need to run background tasks, send emails asynchronously, or process large amounts of data without slowing down your app? This is where Celery comes in!

In this blog, we’ll explore why Celery is essential for Django, how to install it, and how to use it effectively in your projects.


Why Use Celery in Django?

Django handles user requests synchronously, meaning if a task takes too long, the user has to wait. This is problematic for:

Sending Emails – A user shouldn’t have to wait for an email confirmation to be sent.
Generating Reports – Large PDF or Excel reports can take time.
Processing Payments – Payment processing should happen in the background.
Database Backups – Running backups without affecting performance.
Scraping & API Calls – Making API requests without blocking the app.

Celery solves this problem by handling tasks asynchronously in the background using worker processes.

Installing Celery in Django

Before using Celery, ensure you have Redis or RabbitMQ and for windows you can use Memurai installed as a message broker. Redis is the most commonly used and easy to set up.

1️⃣ Install Redis

For Linux/macOS, install Redis using:

sudo apt install redis  # Ubuntu/Debian

brew install redis  # macOS (Homebrew)

For Windows, you can use Docker:

docker run -p 6379:6379 -d redis:alpine

You can use alternate of Redis call Memurai:

=> To install memurai use your cmd write winget search memurai

=> That will tell you the which version of memurai is available

=> Then use command to install memurai

=> winget install Memurai.MemuraiDeveloper

2️⃣ Install Celery in Your Django Project

pip install celery

If you want to install celery for cronjob it auto do task on daily basis or weakly or monthly install celery-beat

pip install django-celery-beat

Configuring Celery in Django

1️⃣ Update Django Settings

Open your settings.py and add the following configuration for Redis/Memurai:

CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
INSTALLED_APPS = [
# Other apps...
'django_celery_beat',
]

2️⃣ Create a Celery Configuration File

Inside your Django project folder, create a new file celery.py:

import os
from celery import Celery
from celery.schedules import crontab
# Set the default Django settings module for the 'celery' program.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "weather_checking.settings")

app = Celery("weather_checking")

# Load task modules from all registered Django app configs.
app.config_from_object("django.conf:settings", namespace="CELERY")

# Auto-discover tasks from installed apps
app.autodiscover_tasks()


app.conf.timezone = "UTC"

If you want to use crontab then afterapp.autodiscover_tasks() write the code:

app.conf.beat_schedule = {
"generate_pdf_daily": {
"task": "weatherapp.tasks.generate_pdf",
"schedule": crontab(minute="*"), # Runs after every five minutes
'args': ('weather.html', {"title": "Generated PDF", "content": "This PDF was created using Jinja2."}, 'generated_report.pdf'),
},
}

3️⃣ Modify __init__.py to Load Celery Automatically

Open __init__.py inside your project folder and add:

from .celery import app as celery_app

__all__ = ("celery_app",)

Using Celery: Creating Your First Task

Let’s create a simple Celery task inside a Django app (e.g., tasks.py).

1️⃣ Create a Celery Task

Inside one of your Django apps (e.g., myapp), create a tasks.py file:

write code for generating pdf

import json
import os
from celery import shared_task
import pdfkit
from jinja2 import Environment, FileSystemLoader
from PyPDF2 import PdfMerger
from django.conf import settings
@shared_task
def generate_pdf(json_data, filename):
"""Generate PDF from a Jinja2 template"""
template_data = json.loads(json_data)
# Load Jinja2 template
template_dir = os.path.join(settings.BASE_DIR, "weatherapp/templates")
env = Environment(loader=FileSystemLoader(template_dir))
pdf_files = []
try:
for i, item in enumerate(template_data):
template_name = item["template"]
context = item["context"]

# Render template
template = env.get_template(template_name)
html_content = template.render(context)

# Convert HTML to PDF
pdf_options = {
'page-size': 'A4',
'encoding': 'UTF-8',
'no-outline': None, # Prevents missing characters in some cases
'enable-local-file-access': '', # Needed if using local fonts
'no-stop-slow-scripts': '', # Allows JavaScript to load images before rendering
'javascript-delay': 10000, # Waits 10 seconds to load all resources (adjust as needed)
'enable-local-file-access': '', # Allow access to local and external image
}
pdf_data = pdfkit.from_string(html_content, False, options=pdf_options)

# Save each PDF separately
pdf_path = os.path.join(settings.MEDIA_ROOT, f"pdfs/{filename}_part_{i}.pdf")
with open(pdf_path, "wb") as f:
f.write(pdf_data)

pdf_files.append(pdf_path)

# Merge all PDFs into one
merger = PdfMerger()
for pdf in pdf_files:
merger.append(pdf)

merged_pdf_path = os.path.join(settings.MEDIA_ROOT, f"pdfs/{filename}.pdf")
merger.write(merged_pdf_path)
merger.close()

return merged_pdf_path

except Exception as e:
return {"error": str(e)}

2️⃣ Calling Celery Tasks in Django

You can call this Celery task in Django views or models:

from django.shortcuts import render
from .weather_utils import fetch_weather_data
from django.http import JsonResponse
from .tasks import generate_pdf
import json

def weather_view(request):
weather_details = fetch_weather_data()
return render(request, "weather.html", {"weather_details": weather_details})


def page_copy(request):
return render(request, 'page_copy.html')


def hidden_widget(request):
return render(request, 'hidden_search_widget.html')


def generate_pdf_view(request):
"""Fetch weather data and trigger PDF generation asynchronously"""
weather_details = fetch_weather_data() # Ensure data is available

template_data = [
{"template": "weather.html", "context": {"weather_details": weather_details}},
{"template": "hidden_search_widget.html", "context": {"page_details": "This is some text for page copy"}},
]
#template_name = "weather.html"
#context = {"weather_details": weather_details} # Pass actual data
filename = "generated_weather_report"
json_data = json.dumps(template_data)
task = generate_pdf.delay(json_data, filename)
return JsonResponse({"task_id": task.id, "status": "Processing"})

3️⃣ Start Celery Worker

First start the project:

python manage.py runserver

Run the Celery worker in a new terminal window:

celery -A your_project worker --loglevel=info

If you want to run auto task run celery-beat in a new terminal:

celery -A weather_checking beat --loglevel=info


1. Run Celery Beat in the Background (Windows)
Use the start command in Command Prompt (cmd):
start celery -A weather_checking worker --loglevel=info --pool=solo

start celery -A weather_checking beat --loglevel=info
This will open a new terminal window and run Celery Beat in the background.

2. Run Celery Beat in the Background (Linux/Mac)
Use the nohup command:
nohup celery -A weather_checking worker --loglevel=info --pool=solo > worker.log 2>&1 &

nohup celery -A weather_checking beat --loglevel=info > beat.log 2>&1 &
This allows Celery Beat to keep running even if you close the terminal.

3. Run Celery Beat as a Background Process (Windows PowerShell)
Start-Process -NoNewWindow -FilePath "celery" -ArgumentList "-A weather_checking worker --loglevel=info --pool=solo"

Start-Process -NoNewWindow -FilePath "celery" -ArgumentList "-A weather_checking beat --loglevel=info"
This starts the process without opening a new window.

4.Running Celery as a Systemd Service (Linux)
For Linux (Ubuntu, Debian, CentOS, etc.), you can create systemd service files.

1️⃣ Create a Service for Celery Worker
1 Open a terminal and create a new service file:

sudo nano /etc/systemd/system/celery_worker.service

2 Add the following content (adjust paths accordingly):

[Unit]
Description=Celery Worker
After=network.target

[Service]
Type=forking
User=yourusername
Group=yourusername
WorkingDirectory=/path/to/your/project
ExecStart=/path/to/your/venv/bin/celery -A weather_checking worker --loglevel=info --pool=solo
Restart=always

[Install]
WantedBy=multi-user.target

Replace yourusername with your actual Linux username.
Replace /path/to/your/project with your project directory.
Replace /path/to/your/venv/bin/celery with the path to Celery in your virtual environment.

2️⃣ Create a Service for Celery Beat

Create another service file:

sudo nano /etc/systemd/system/celery_beat.service
Add:

[Unit]
Description=Celery Beat Scheduler
After=network.target

[Service]
Type=forking
User=yourusername
Group=yourusername
WorkingDirectory=/path/to/your/project
ExecStart=/path/to/your/venv/bin/celery -A weather_checking beat --loglevel=info
Restart=always

[Install]
WantedBy=multi-user.target

3️⃣ Enable & Start the Services
After creating the service files, reload systemd and start the services:

# Reload systemd
sudo systemctl daemon-reload

# Enable both services to start at boot
sudo systemctl enable celery_worker
sudo systemctl enable celery_beat

# Start the services now
sudo systemctl start celery_worker
sudo systemctl start celery_beat
4️⃣ Check the Service Status
You can check if Celery is running using:

sudo systemctl status celery_worker
sudo systemctl status celery_beat
If there are any errors, check logs with:

journalctl -u celery_worker --no-pager --lines=50
journalctl -u celery_beat --no-pager --lines=50
5️⃣ Restart or Stop Celery
If you need to restart or stop Celery services:

# Restart Celery Worker
sudo systemctl restart celery_worker

# Restart Celery Beat
sudo systemctl restart celery_beat

# Stop Celery Worker
sudo systemctl stop celery_worker

# Stop Celery Beat
sudo systemctl stop celery_beat


🔹 Monitoring Celery Tasks

You can check the status of Celery tasks using Flower, a real-time task monitoring tool:

pip install flower celery -A your_project flower

Now, open http://localhost:5555 in your browser to monitor tasks.


🔹 Conclusion: Why Celery is a Game Changer for Django

Celery is an essential tool for asynchronous processing in Django applications. It ensures:

✅ Faster response times for users
✅ Scalable and efficient background task execution
✅ Better resource management for long-running tasks

By following this guide, you can integrate Celery into your Django projects for handling background tasks effortlessly! 🚀


No comments

Powered by Blogger.