How do I get signals.py executed in this django environment?

I'm trying to run the following signals.py

from .models import Sale
from django.db.models.signals import m2m_changed
from django.dispatch import receiver

print("running")

@receiver(m2m_changed, sender=Sale.positions.through)
def calculate_total_price(sender, instance, action, **kwargs):
    print('action', action)
    print("running2")

    total_price = 0
    print("running3")
    if action == 'post_add' or action == 'post_remove':
        print("running4")
        for item in instance.get_positions():
            total_price += item.price
            print("running5")
    
    instance.total_price = total_price
    instance.save()

apps.py already signals in VSCode that signals is not used

from django.apps import AppConfig


class SalesConfig(AppConfig):
    #default_auto_field = 'django.db.models.BigAutoField'
    name = 'sales'

def ready(self):
    import sales.signals

and then the init.py file

default_app_config = 'sales.apps.SalesConfig'

For completeness I'll add the models.py

from django.db import models
from products.models import Product
from customers.models import Customer
from profiles.models import Profile
from django.utils import timezone
from .utils import generate_code
# Create your models here.

class Position(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField()
    price = models.FloatField(blank=True)
    created = models.DateTimeField(blank=True)

    def save(self, *args, **kwargs):
        self.price = self.product.price * self.quantity
        return super().save(*args, **kwargs)

    def __str__(self):
        return f"id: {self.id}, product: {self.product.name}, quantity: {self.quantity}"

class Sale(models.Model):
    transaction_id = models.CharField(max_length=12, blank=True)
    positions = models.ManyToManyField(Position)
    total_price = models.FloatField(blank=True, null=True)
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    salesman = models.ForeignKey(Profile, on_delete=models.CASCADE)
    created = models.DateTimeField(blank=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"Sales for the amount of ${self.total_price}"

    def save(self, *args, **kwargs):
        if self.transaction_id == "":
            self.transaction_id = generate_code()
        if self.created is None:
            self.created = timezone.now()
        return super().save(*args, **kwargs)

    def get_positions(self):
        return self.positions.all()

class CSV(models.Model):
    file_name = models.FileField(upload_to='csvs')
    activated = models.BooleanField(default=False)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return str(self.file_name)

I have Ubuntu2204 running in a WSL2 Windows11 environment, Django 4.1.1 & Python 3.10 - not sure if this could be causing the issues here?!

I just noticed that your ready identation is not correct, causing the problem...

You should change this:

from django.apps import AppConfig


class SalesConfig(AppConfig):
    #default_auto_field = 'django.db.models.BigAutoField'
    name = 'sales'

def ready(self):
    import sales.signals

To this:

from django.apps import AppConfig


class SalesConfig(AppConfig):
    #default_auto_field = 'django.db.models.BigAutoField'
    name = 'sales'

    def ready(self):
        from . import signals

Generally because no indentation the method became global function and it was not called as it should.

Back to Top