On Wed, Apr 21, 2010 at 5:09 PM, Tim Shaffer <t...@tim-shaffer.com> wrote: > I think then you will run into a problem with you add another media > type: > > class WAVMedia(Media): > file = models.CharField() > def play(self): > # do stuff > >>>> m = Media() >>>> m.wavmedia = WAVMedia() >>>> m.mp3media = MP3Media() >>>> playlist = Playlist >>>> playlist.media_set.append(m) > > for media in playlist.media_set.all(): > media.play() > > Should media.play() call play() on the Media class, WAVMedia class, or > the MP3Media class? It *should* call it on the Media class, which it > does, since you have an instance of Media. And even you wanted it to > call the play method on MP3Media or WAVMedia, how would you determine > which one to call? But this is the way multiple table inheritance is > supposed to work. This is the way python works:
Well, no clearly not - those are all base instances. The point is that polymorphism, forget python or django for a second, a standard feature of most programming languages would say that if you get a Derived type addressed as a Base type, then calling a virtual function on it would call the Derived method. Python sorts this out by not allowing you to alias a Derived type as a Base type, except explicitly by calling the Base type as a class function and passing in a Derived instance as 'self'. If you create an instance of Base, its not a Derived - ever! With Django's MTI, you *can* get a Derived type aliased as a Base type, due to the way MTI works. This isn't a problem (it certainly isn't one for me!), it's just something to be aware of. The OP wasn't, and that's why we're having this discussion! > > class Media(object): > pass > > class MP3Media(object): > def play(self): > # pass > > If I have the following list: > > songs = [ Media(), Media(), Media() ] > > I would never expect to be able to call play() on any instance in that > list. Why would Django be any different? > > I think in both these cases (there is no person actually an instance > of "Person", and there should be no actual instance of "Media"), it > would be best to mark the parent class abstract and use a generic > relation (like you said) to join to either MP3Media or WAVMedia. This > is the "Django way" and I believe is the functionality you're looking > for. No, it really isn't. I've obviously missed off a whole slew of things from this example model, but there are a HOST of common options for a Media class that are generic and non-specific to a type of Media. Not storing this homogeneously would be a bit crap, don't you think? You wouldn't be able to find media with a playlength more than 5 minutes, only MP3Media, or WAVMedia, or.... As I mentioned, GFKs are the way to achieve the solution, which does do everything needed, there's just no need to go to abstract inheritance. I'd alter your models to not use abstract inheritance, add a GFK on Media to point at the specific instance of the media: class Media(models.Model): content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() media = generic.GenericForeignKey() class MP3Media(Media): def play(self): print "playing mp3" class WAVMedia(Media): def play(self): print "playing wav" class Playlist(models.Model): media = models.ManyToManyField('Media') for m in my_playlist.media_set.all(): m.media.play() This is what I was trying to say in my previous reply ;) Cheers Tom -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.