Using django signals to update status of multiple models

I'm currently working on a Django project where I have models for ClientOrders, DesignerJob, and PrinterJob. I want to implement a functionality where changes in the status of DesignerJob and PrinterJob models trigger updates to the status of the associated ClientOrders model.

For example, when the status of a DesignerJob changes from "new" to "in_progress," I want the status of the corresponding ClientOrders model to be updated to a specific status. Similarly, when the status of a PrinterJob changes, I want the associated ClientOrders status to be adjusted accordingly.

I'm planning to use Django signals to achieve this, but I want to make sure I follow best practices and avoid potential pitfalls.Here are my specific questions:

Signal Handling Approach: Should I use one signal for each model and implement all the conditions in that signal or make separate signals for each case?

Circular Signal Calling: If I have a case where say PrinterJob signal updates DesignerJob status, will it cause circular calling? But this case is very unlikely.

class ClientOrders(models.Model):
franchise = models.ForeignKey(
    Franchise, on_delete=models.CASCADE, null=True)
order_id = models.CharField(max_length=100, default=0 , unique=True)
order_type = models.CharField(max_length=50, default='shop')
payment_method = models.CharField(max_length=50, default='cash')
card_no = models.CharField(max_length=16, default='', blank=True)
expiry = models.CharField(max_length=50, default='', blank=True)
sub_total = models.IntegerField(default=0)
shipping_amount = models.IntegerField(default=0)
tax = models.IntegerField(default=0)
total_price = models.IntegerField(default=0)
henry_order_id = models.CharField(max_length=100, default="")
status = models.IntegerField(choices=ORDER_STATUS, default=0)
shipping_address = models.CharField(max_length=255, default='')
phone_number = models.CharField(max_length=15, null=True)
created_at = models.DateTimeField(auto_now_add=True)
is_removed = models.BooleanField(default=False)


class ClientOrderItems(models.Model):
order_id = models.ForeignKey(
    ClientOrders, on_delete=models.CASCADE, null=True)
size = models.ForeignKey(
    FranchiseMaterial, on_delete=models.CASCADE, null=True)
franchise_product = models.ForeignKey(
    FranchiseProduct,
    on_delete=models.CASCADE,
    related_name = 'franchise_products',
    null=True
)
scan_id = models.CharField(max_length=255, null=True)
stand_id = models.IntegerField(null=True)
quantity = models.IntegerField(default=0)
unit_price = models.IntegerField(default=0)
stand_price = models.IntegerField(default=0, null=True, blank=True)
total_price = models.IntegerField(default=0)
customer_payment_method = models.CharField(max_length=20)
customer_card = models.CharField(max_length=16, default='', blank=True)
card_brand = models.TextField(max_length=50, null=True)
customer_name = models.CharField(max_length=50)
customer_email = models.EmailField(null=True)
customer_phone = models.CharField(max_length=50, null=True)
customer_id = models.IntegerField(default=1)
customer_shipping_addresss = models.CharField(max_length=255)
product_name = models.CharField(max_length=50, null=True)
product_url = models.CharField(max_length=255, null=True)
adults = models.IntegerField(default=0, null=True)
child = models.IntegerField(default=0, null=True)
notes = models.TextField(max_length=1000, null=True)
henry_item_id = models.CharField(max_length=100, default="")
henry_status = models.CharField(max_length=100, default='')
created_at = models.DateTimeField(auto_now=True)
is_removed = models.BooleanField(default=False)
model_uploaded = models.BooleanField(default=False)
item_type = models.CharField(max_length = 100 , choices = ITEM_CHOICES , default = 'figurine') 


class DesignerJob(BaseModel):
designer = models.ForeignKey(DesignerProfile, on_delete=models.CASCADE, null=True)
order_item = models.OneToOneField(ClientOrderItems, on_delete=models.CASCADE)
operator = models.TextField(unique=False)
revisions = models.FloatField(default=0.0)
job_id = models.CharField(max_length=100, unique=True, null=True)
status = models.CharField(max_length=50, choices=JOB_STATUS, default="open")
special_instruction = models.TextField(null=True)
designer_comments = models.TextField(null=True)
rate = models.FloatField(default=10.0)
old_price = models.FloatField(null=True)
file_uploaded = models.BooleanField(default=False)
assigned_time = models.DateTimeField(null = True)

class PrinterJob(BaseModel):
printer = models.ForeignKey(Printer, on_delete=models.CASCADE, null=True, blank=True)
designer_job = models.ForeignKey(DesignerJob, on_delete=models.CASCADE)
order_id = models.ForeignKey(ClientOrders, on_delete=models.CASCADE)
status = models.CharField(max_length=50,choices=PRINT_JOB_STATUS,default="in_touch_up")
Back to Top