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.

Reply via email to