1

I am using django 2.0.8 and Python 3.5. I have written a base class which encapsulates behavior in a base class.

When using the interface in the child class, I find that I have to pass the object of the child class to the parent - which is not only ugly, is error prone.

I do not want to use composition (instead of an interface), because AFAIK fields in django models are saved to the DB - that aside, I prefer the sub classing approach, since all the functionality can remain in the base class.

Is there any way I can (in the parent class), find/obtain the instance (or at least the name of the class and it's id) that invoked the method call?

Here is my code:

class Likeable(models.Model):
    likes = GenericRelation(Like)


    def action_is_permissible(self, actionable_object, actor):
        ct = ContentType.objects.get_for_model(actionable_object)
        object_id = actionable_object.id
        found_objects = Like.objects.filter(content_type=ct, object_id=object_id, liker=actor)

        return ((len(found_objects) == 0), ct, object_id, found_objects)


    def add_like(self, actionable_object, actor):

        can_add, ct, object_id, found_objects = self.action_is_permissible(actionable_object, actor)

        if can_add:
             like = self.likes.create(content_type=ct, object_id=object_id, liker=actor)
        else:
            # do nothing
            return


    class Meta:
        abstract = True


class Foo(Likeable):
    name = models.CharField(max_length=255,default='')
    objects = models.Manager()

Example use (imports omitted)

foo = Foo.objects.get(id=1)
p = User.objects.get(id=1)

foo.add_like(foo, p) # <- nasty API calling convention
Homunculus Reticulli
  • 65,167
  • 81
  • 216
  • 341

1 Answers1

0

You can access it using self.
self refers to the object which is calling.

Ref: What is the purpose of self?

EDIT (code changes):

class Likeable(models.Model):
    def add_like(self, actor):
        # update `actionable_object` to `self`

foo.add_like(p)
Sachin
  • 3,576
  • 1
  • 15
  • 24
  • Look at the usage example. I can't invoke `foo.add_like(self, p)` in code - as `self` would be unidentified. Look at the signature of the `add_like` method in the base class. – Homunculus Reticulli Sep 05 '18 at 17:27
  • You dont have to pass `self` yourself. Python does that for you. – Sachin Sep 05 '18 at 17:28
  • Sigh ... you don't seem to grasp what the problem is here. The method is **implemented** in the subclass (i.e. parent class of Foo): *Likeable*. At the point where the method is called, `self` points to an instance of the `Likeable` class. The problem is that I don't know how (or indeed if it's possible) to obtain an instance of the **CHILD** (in this case Foo) who invoked the method at the point that the code is being executed from within the `Likeable` class. Put simply, I'm trying to "reach out" from the `Likeable` class to see which class invoked the method. – Homunculus Reticulli Sep 05 '18 at 17:34
  • "`The method is implemented in the subclass`". I think you meant that the method is implemented in the parent class. And, I tried this code. `self` does refer to `foo` and `self.id` prints out the `id` of the `foo` object. – Sachin Sep 05 '18 at 17:44
  • You're right, I mispoke. I sometimes get confused switching over from C++ and other languages (where the naming convention seems to be different) to Python. **method is implemented in the parent class.** – Homunculus Reticulli Sep 05 '18 at 17:48
  • OK. You were right. I'm going to stand in the corner and face the wall - whilst I scream for a few minutes! I think now would be a good time to take a coffee break! :D – Homunculus Reticulli Sep 05 '18 at 18:02
  • Yes, you do need a break. But, it's okay, sometimes, these things happen :P – Sachin Sep 05 '18 at 18:05