Reputation: 684
I want to separate some logic from model and group it in a property, just like Django does with model managers (object
property). I fact, something like ForeignKey
but without database representation.
I have something like this:
class Remote(object):
def __init(self, *args, **kwargs)
self.post = ... # how to get to post instance?
def synchronize(self):
# this function requires Post object access
print(self.post.name)
class Post(models.Model):
name = models.CharField(max_length=100)
remote = Remote()
...
for post in Post.objects.all():
post.remote.synchronize()
Question
How to modify above code to get access to Post
object in Remote
object?
Additional question
Is it possible to determine if Remote
object has been called from Post
instance (post.remote...
– like above) or Post
class (Post.remote...
)?
Upvotes: 2
Views: 1173
Reputation: 986
What you want here can be achieved with descriptors.
In order for it to work, you need to define a __get__
method in your class that you want to be accessible as an attribute of another class.
A simple example for your case will look like this:
class Remote:
def __init__(self, post)
self.post = post
def synchronize(self):
print(self.post.name)
class RemoteDescriptor:
def __get__(self, obj):
if not obj:
return self
remote = getattr(obj, '_remote', None)
if not remote:
remote = Remote(obj)
obj._remote = remote
return remote
class Post(models.Model):
name = models.CharField(max_length=100)
remote = RemoteDescriptor()
Explanation:
In the above code, every time you call an attribute remote of your Post
model, __get__
method of the RemoteDescriptor
will be invoked. First check for obj is to make sure that descriptor is called from other object, not directly. Two classes Remote and RemoteDescriptor are needed here in order for you to be able to add custom methods inside your descriptor accessible using dot (e.g. post.remote.calculate()
)
Note also that I am placing the instance of Remote
to the dict of Post on first invokation and on all subsequent calls, object will be returned from there.
You should also check a great article on descriptors on RealPython.
Upvotes: 3