0

I want to get the class of the sender in the code below using sender.__class__. This works until I have a model that inherits from a base class.

For example sender is class Profile but sender.__class__ gives the base bass Profile inherits from MPTTModelBase (which is abstract = True). Same thing with .Meta etc.

@receiver(post_save)
def send_func(sender, instance, created, **kwargs):

    print(sender) #<class 'demo.apps.t.models.Profile'>
    print(sender.__class__) # <class 'mptt.models.MPTTModelBase'>

How do I get the class ignoring inherited models (if it has one)?

Prometheus
  • 32,405
  • 54
  • 166
  • 302
  • 1
    `sender` *is* the class itself for this signal. – spectras Oct 06 '15 at 09:48
  • I see, so ``sender.__class__`` is going down another level? But why if I do ``sender.Meta`` does it get the MPTTModelBase Meta. should it not get senders? – Prometheus Oct 06 '15 at 09:52
  • 1
    Indeed, `sender.__class__` gets you the [metaclass](http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python). You would use `sender._meta` to access the meta options once the class has been loaded. – spectras Oct 06 '15 at 09:59
  • I see that makes sense now. could you add this as an answer for me to accept? – Prometheus Oct 06 '15 at 10:13

1 Answers1

1

For most django signals, the sender of the signal is the class itself. Here, you get sender as the class and the actual object is instance.

So what you will get is:

  • sender.__class__: the metaclass of your model.
  • sender._meta: the model's Meta options. You get it here because Django removes the Meta from the model and makes options available as _meta, which it augments with some methods.
Community
  • 1
  • 1
spectras
  • 13,105
  • 2
  • 31
  • 53
  • Yes, it is very handy for all kind of generic code that needs to examine the model. If you use a version of Django older than 1.8, beware that it changed a lot from django 1.7 to django 1.8. – spectras Oct 06 '15 at 10:28