How to Use Django pre_save and post_save Signals Effectively

By khoanc, at: March 15, 2025, 8:01 p.m.

Estimated Reading Time: __READING_TIME__ minutes

How to Use Django pre_save and post_save Signals Effectively
How to Use Django pre_save and post_save Signals Effectively

Django signals are a powerful tool for decoupling logic in your application. The pre_save and post_save signals, in particular, allow developers to execute custom actions before or after saving a model instance to the database. These signals are ideal for automating tasks, reducing manual intervention, and maintaining cleaner code.

In this blog post, we’ll explore how to use these signals effectively by presenting a real-world case study: managing warehouse inventory and sending low stock notifications.

 

Real-World Case Study: Smart Warehouse Inventory Management

 

The Scenario


Imagine you’re building an inventory management system for a warehouse. Each time a product is added or updated:
 

  1. The total product count in the warehouse must be updated automatically.
     
  2. If the product quantity falls below a threshold, the warehouse owner must be notified via email to prevent stockouts.
     

This workflow ensures the warehouse runs efficiently, eliminates manual tracking, and prevents inventory shortages.

 

Implementation

 

Step 1: Define the Models


We’ll start by creating two models:
 

  1. Warehouse: Stores the total count of all products.
     
  2. Product: Represents individual products linked to a warehouse.
     

from django.db import models

class Warehouse(models.Model):
    name = models.CharField(max_length=255)
    total_products = models.PositiveIntegerField(default=0)

    def __str__(self):
        return self.name


class Product(models.Model):
    name = models.CharField(max_length=255)
    quantity = models.PositiveIntegerField(default=0)
    warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE, related_name="products")

    def __str__(self):
        return self.name

 

Step 2: Connect Signals for Automation


We’ll use two signals:
 

  1. pre_save to adjust the warehouse’s total product count before saving.
     
  2. post_save to send an email notification if the product quantity is low.
     
 

from django.db.models.signals import pre_save, post_save
from django.dispatch import receiver
from django.core.mail import send_mail
from .models import Product, Warehouse


@receiver(pre_save, sender=Product)
def update_total_products(sender, instance, **kwargs):
    if instance.pk:
        # Fetch the old quantity from the database
        old_quantity = Product.objects.get(pk=instance.pk).quantity
        difference = instance.quantity - old_quantity
    else:
        difference = instance.quantity

    # Update the warehouse's total product count
    instance.warehouse.total_products += difference
    instance.warehouse.save()


@receiver(post_save, sender=Product)
def send_low_stock_notification(sender, instance, **kwargs):
    low_stock_threshold = 10  # Low stock threshold
    if instance.quantity < low_stock_threshold:
        # Send an email notification to the owner
        send_mail(
            subject=f"Low Stock Alert: {instance.name}",
            message=f"The product '{instance.name}' is running low with only {instance.quantity} items remaining. Please restock soon.",
            from_email="[email protected]",
            recipient_list=["[email protected]"],  # Replace with the warehouse owner's email
        )

 

Step 3: Register the Signals


Ensure the signals are registered when the app is ready by importing them in the apps.py file.

# apps.py
from django.apps import AppConfig

class InventoryConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "inventory"

    def ready(self):
        import inventory.signals  # Import signals

 

Testing the System

 

Add a New Product
 

Create a new product and verify the warehouse's total product count updates automatically.

warehouse = Warehouse.objects.create(name="Main Warehouse")
product = Product.objects.create(name="Widget", quantity=20, warehouse=warehouse)
print(warehouse.total_products)  # Output: 20


Update Product Quantity


Update the product quantity and ensure the warehouse total reflects the change.

product.quantity = 35
product.save()
print(warehouse.total_products)  # Output: 35

 

Low Stock Notification


Reduce the product quantity below the threshold and check for an email notification.

product.quantity = 5
product.save()
# Email sent: "The product 'Widget' is running low with only 5 items remaining."

 

Benefits of This Approach
 

  1. Automation

    Warehouse totals and low stock alerts are handled automatically, eliminating the need for manual updates.
     

  2. Proactive Notifications

    Owners are alerted about low stock before it becomes a critical issue, ensuring smooth operations.
     

  3. Decoupled Logic

    Signals keep the inventory logic separate from the core application, making the system more modular and maintainable.

 

Best Practices for Using Django Signals
 

  1. Avoid Complex Logic

    Keep signal handlers simple. For heavy tasks like sending emails, consider using a background task queue like Celery.
     

  2. Minimize Signal Overhead

    Ensure signals don’t perform unnecessary database queries or slow down request handling.
     

  3. Test Signal Behavior

    Test thoroughly to ensure signals trigger as expected and don’t interfere with other parts of the application.

 

Conclusion


Django’s pre_save and post_save signals are excellent tools for automating workflows and keeping your application logic clean. In this case study, we’ve shown how signals can streamline inventory management by automatically updating warehouse totals and notifying owners of low stock.

By implementing these techniques, you can build smarter, more efficient systems that save time and prevent costly errors.

Ready to optimize your Django app? Start leveraging signals today!

Tag list:
- Django signal for product quantity updates
- Django pre_save post_save use cases
- How to use Django signals
- Automate inventory workflows Django
- Low stock email notification Django
- Best practices for Django signals
- Django signals tutorial
- Real-world Django signal case study
- Django pre_save signal
- Automate tasks with Django signals
- Django warehouse inventory management
- Django post_save signal
- Using Django signals effectively
- Warehouse product management Django
- Django signal example

Related

Python Learning

Xero API integration with Python

Read more
Django rest framework Django

[One Package Per Day] - Django Filter

Read more
Great Sites

[Useful Site Review] visily.ai

Read more

Subscribe

Subscribe to our newsletter and never miss out lastest news.