Question

This is a follow up question to : Cant get post_save to work in Django

My models are :

class Car(models.Model):
    name = models.CharField(max_length=50)
    ...
    some other attributes of Car
    ...

class Person(models.Model):
    car = models.ManyToManyField(Car)
    name = models.CharField(max_lenght=100)
    ...
    Some other attributes of Person
    ...


class License(models.Model):
    person = models.ForeignKey(Person)
    ...
    Other attributes of License
    ...

Signal handler:

def signal_handler(sender, **kwargs):
    print 'Person saved!'
    generate_license()

post_save.connect(signal_handler, sender=Person, dispatch_uid="Unique person")

The intent: When an instance of Person is created, I want to generate a License object. So I filter out the last tuple that was added into License and then use its contents to generate a License instance.

def generate_license():
    import pdb
    pdb.set_trace()
    man = Person.objects.filter().order_by('-time_added')[:1][0] # Restricting the filter to one query and then taking the value at the 0th index. order_by '-time_added' gives the latest tuple at the top.
    license = License.objects.create(...Info about car, person...)

The Error:

An example: Say Car has 3 instances:

  1. BMW
  2. FERRARI
  3. LAMBORGHINI

Now when I add an instance of Person from the admin, example:

per be an instance with car = BMW, FERRARI and name = Bob When I click save in admin, the set_trace() starts. So after the query in generate_license :

In pdb, when the query executes, I try printing out per.car.all() but it gives me [] and when I try printing out per.name, it does print out Bob. So I am not really getting as to how per.name is saved and per.car isnt.

Also, when the request is completed, that is I have pressed c in pdb, I again click on save for the same instance, this time it reads the per.car.all() perfectly while if before saving, I added LAMBORGHINI, it only shows up BMW and FERRARI. So what I guess is happening is that the many-to-many field is coming a request late. Although I can't point out the reason for this. Need some help. Am I missing something?

Question: Is there a specific way to identify an update signal from a create signal? I mean I do not want to generate a new License every time a data is updated. A new License will only generate when the data has been created. So, how to distinguish between update and save signals?

Was it helpful?

Solution

post_save does not work on m2m fields. You have to use the m2m_changed signal.

Something like this:

def my_m2m_signal(sender, **kwargs):
    action = kwargs.get('action')
    if action == 'post_add':
        print 'post_add is activated on m2m'

signals.m2m_changed.connect(my_m2m_signal, sender=Person.car.through)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top