Reputation: 6777
Is there an elegant way to handle all get
requests of a class when I just want to pass the get
to another object?
This is a Django project where I have a Video model; the Video can be from different sites (e.g., YouTube, Vimeo, etc). The model is generic and will grab the appropriate backend
to parse the data (which will be repr
differently depending on the site). All Videos will have the same properties but I have a different backend
to parse them correctly. Here is the example:
BACKEND_VIDEO_TYPE = (
(1, 'YouTube'),
(2, 'Vimeo'),
)
class Video(ItemBase):
video_id = models.CharField(max_length=25)
video_type = models.PositiveIntegerField(choices=BACKEND_VIDEO_TYPE)
video_data = models.TextField(editable=False)
class Meta:
unique_together = ("video_id", "video_type")
def __init__(self, *args, **kwargs):
super(Video, self).__init__(*args, **kwargs)
for k, v in BACKEND_VIDEO_TYPE:
if k == self.video_type:
VideoBackend = import_string( 'video.backends.' + v )
# load the backend that matches the video type and supply it with the data to parse
self.backend = VideoBackend(self.video_id, self.video_data)
@property
def link(self):
return self.backend.link
@property
def thumbnail(self):
return self.backend.thumbnail
@property
def is_public(self):
return self.backend.is_public()
@property
def duration(self):
return self.backend.duration
I don't feel like this is the best way to handle this but I am too new to know what to look for. AFter I identify which backend class to implement, is there an easy way to return self.backend.property
without having to add each property that is in the backend? The list is going to get rather long. A generic __get__
or similar?
Thanks for your help.
Upvotes: 0
Views: 89
Reputation: 8999
You could override __getattr__
on the Video
class so that it fetches an attribute of backend
.
def __getattr__(self, attr):
try:
return getattr(self.backend, attr)
except:
raise AttributeError('No attribute named ' + attr)
__getattr__
will only call if the attribute is not found on the Video
object (e.g. it wouldn't call at all if the user asked for Video.video_id
) so it's a neat way to extend the exposed attributes of the Video
class. The downside is that it may not be obvious which attributes are available, or it may expose some attributes you don't wish to. You could get around this by having the VideoBackend
class provide a list of allowed attributes.
def __getattr__(self, attr):
if attr in self.backend.get_allowed_attr():
return getattr(self.backend, attr)
else:
raise AttributeError('No attribute named ' + attr)
Upvotes: 1