I have three abstract base classes: DataContainer, BaseFileContainer and BaseImageContainer.
class BaseFileContainer(m.Model):
class Meta:
abstract = True
# file - internally hosted file
file = m.FileField(upload_to=archive_path, blank=True)
class BaseImageContainer(m.Model):
class Meta:
abstract = True
# image - internally hosted file
image = m.ImageField(upload_to=archive_path, blank=True)
class DataContainer(BaseDataContainer):
class Meta:
abstract = True
# choices
# render information for this hoster
YOUTUBE = 'yt'
render_type_choices = (
(YOUTUBE, _('YouTube')),
)
# automatic properties
cr_date = m.DateTimeField(auto_now_add=True, editable=False, verbose_name=_('Date of Creation')) # date of creation
# data type
# common properties
internal = m.BooleanField(default=True)
# external - externally hosted data
render_type = m.CharField(max_length=2, choices=render_type_choices, blank=True) # a renderer for the hoster
url = m.URLField(blank=True)
# internal
downloadable = m.BooleanField(default=False)
# meta information
name = m.CharField(max_length=255)
created_on = m.DateTimeField(blank=True) # When was this media created?
created_by = m.CharField(max_length=255, blank=True) # Who created it?
created_at = m.CharField(max_length=255, blank=True) # Where was it created?
notes = m.TextField(blank=True) # Notes for internal use
# relationships with other models
added_by = m.ForeignKey(User, null=True, default=None, on_delete=m.SET_NULL, editable=False)
These classes become concrete in these two classes:
class BaseImage(DataContainer, BaseImageContainer):
pass
class BaseFile(DataContainer, BaseFileContainer):
pass
I have a method defined for DataContainer that retrieves the media url. In order to do this, I need to either access the child class BaseFileContainer or BaseImageContainer.
def get_media_url(self):
if self.internal and self.downloadable:
if hasattr(self, 'file'):
url = format_html(LINK, getattr(self, 'file').url, self.name)
if hasattr(self, 'image'):
url = format_html(LINK, getattr(self, 'image').url, self.name)
elif self.external:
url = format_html(LINK, self.url, self.name)
else:
url = '-'
Is it proper to access child attributes like this or should I rather define the method for the child classes? If I do that, I would have to basically define the same method twice which isnât very DRY. Which way do you think is better?