On Oct 13, 12:16 pm, DrMeers <[EMAIL PROTECTED]> wrote: > I am writing a Blog-style django site which needs to render a > collection of Item objects. Item is the root Super class for a whole > bunch of sub-classes -- Photo, Video, Quote, News, etc. I want to be > able to iterate through Item.objects.all() and ask each Item to > render() itself based on which sub-class it is. I'm from a C++ > background, and my virtual-method approach isn't working -- it just > calls the Item.render() method instead of the appropriate sub-class > one. > > #Simplified example classes: > class Item(models.Model): > group = models.ForeignKey(ItemGroup) > order = models.IntegerField() > when = models.DateTimeField(null=True, blank=True, help_text="When > the item occured; can be auto-extracted from photos") > added = models.DateTimeField(default=datetime.datetime.now, > editable=False) > def render(self): > return "Plain 'ol item" > > class News(Item): > html = models.TextField() > def render(self): > return "<div class='news'>" + self.html + "</div>" > > class Photo(Item): > original = models.FileField(upload_to='%Y/%m') > def render(self): > return "<img src='%s'>" % (self.original.url) > > class Quote(Item): > #... > > class Video(Item): > #... > > # Now I'd like to be able to iterate through all items in a given > group > # (eg. for i in exampleGroup.item_set.order_by("order") ) > # and call the render function for each Item, regardless of whether it > # is a News, Photo, Quote, Video, etc. Like a virtual function in C++. > # But i.render() just calls the Item.render() method; how can I figure > out > # which subclass the item is, and call the appropriate subclass > method? > > I know this is a bit ugly having HTML in the models, and I should > probably use "inclusion" template tags. Can anyone please point show > me how this should be done?
There's nothing wrong with the approach of iterating through and asking each object to call its own render method - this is the whole point of Python's concept of 'duck-typing'. However, the issue is with how you're getting the objects in the first place. Due to the way model inheritance is implemented, parent objects don't know about their subclasses. So if you just do group.item_set.all() you will just get a series of Item objects. Unfortunately there's no easy way round this. One approach is to give the parent class an item_type field with choices that determine which type it is. Or you can get all the individual subclasses separately and combine them into a list for iterating: list(group.news_set.all()) + list(group.photo_set.all()) etc On the HTML issue, I don't think template tags will necessarily help here. I would stay with the render() on each class, but instead of just returning a literal HTML string I would get the methods to render a template to a string and return that. -- DR. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---