On Wed, Apr 21, 2010 at 2:35 PM, Tim Shaffer <t...@tim-shaffer.com> wrote: > On Apr 21, 9:28 am, Tom Evans <tevans...@googlemail.com> wrote: >> On Wed, Apr 21, 2010 at 2:15 PM, Tim Shaffer <t...@tim-shaffer.com> wrote: >> > On Apr 21, 8:25 am, Torsten Bronger <bron...@physik.rwth-aachen.de> >> > wrote: >> >> calls the method of the respective class of "instance". However, in >> >> Django, >> >> >> for instance in RootClass.objects.all(): >> >> instance.do_something() >> >> >> will *always* call RootClass.do_something(), which is almost never >> >> what you want. >> >> > I don't necessarily think that's a problem at all. That's the way it >> > should work. You want to be able to call RootClass.do_something() on >> > an instance of RootClass and have it run that method from one of the >> > sub classes? >> >> Yes please; this is called 'polymorphism', and is quite a neat >> feature. If I were to run: >> >> instance = Derived() >> instance.func() >> >> then I would want Derived.func to be executed. If, however, I wrote this: >> >> instance = Derived() >> Base.func(instance) >> >> then I would expect Base.func to be executed. > > I think I must be missing something, because I'm pretty sure Django > doesn't change any of that. > > Given the following example.... > > class Author(models.Model): > first = models.CharField(u'First Name', max_length=20) > last = models.CharField(u'Last Name', max_length=20) > > def do_something(self): > print "I'm going to write" > > class Translator(Author): > language = models.CharField(max_length=10) > > def do_something(self): > print "I'm going to translate" > > class Editor(Author): > language = models.CharField(max_length=10) > > def do_something(self): > print "I'm going to edit" > >>>> a = Author(first="Tim", last="Shaffer") >>>> a.translator = Translator(language="English") >>>> a.editor = Editor(language="German") > >>>> t = Translator.objects.all()[0] > > This works as I would expect it to... > >>>> a.do_something() > "I'm going to write" > >>>> t.do_something() > "I'm going to translate" > >>>> Author.do_something(t) > "I'm going to write" > > Calling a.do_something() should *never* call either > Translator.do_something() or Editor.do_something() >
You are absolutely right, its just that django with MTI adds the possibility to get a reference to the base class as a valid object. In raw python, an object that is a Derived is always a Derived, you would never construct it as a Base. In django, you can quite easily create an instance of Base that actually represents a record of a Derived in the database. For instance, if you had something like this: class Playlist(models.Model): media = models.ManyToManyField('Media') class Media(models.Model): date_added = models.DateField() def play(self): raise NotSupportedException class MP3Media(Media): file = models.CharField() def play(self): # do stuff Then you would typically like to get the media and play it: for media in playlist.media_set.all(): media.play() However this would get the base Media class, which cannot be played. The snippets posted above by Torsten allow a simple function to turn Base into Derived in a situation like this. This can mostly be worked around with generic foreign keys, which is the only sane way of handling this IMO. 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.