Many to many field not shown in object while using signals to detect save operation in django

丶灬走出姿态 提交于 2019-12-13 13:17:16

问题


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?


回答1:


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)


来源:https://stackoverflow.com/questions/17263780/many-to-many-field-not-shown-in-object-while-using-signals-to-detect-save-operat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!