On 2008-04-17, at 1553, Justin Fagnani wrote:
> Hey Malcolm, > > I've been using qs-rf for a while now with basically no problems. > Excellent work. > > There's one thing that may a little odd that I stumbled on while > trying to get some primitive polymorphism working: > > The first thing is that there seems to be no way to tell if an > instance of a parent class has a child instance without trying the > child reference and catching the DoesNotExist exception. For a class > with multiple subclasses, this is a cumbersome, so I've been adding > a _type field to parent classes that gets set in save() of the > subclasses. > > Is there a better way to do this, or is this something that could be > included? I know there's no way to determine whether or not a class > will be subclassed in the future, so I wouldn't be surprised if the > answer is no. But maybe there should be a documented pattern. > > The odd part is what happens with the child reference. parent.child > obviously works as expected, and returns either an instance of Child > or raises DoesNotExist. But for an instance of Child, .child always > returns a reference to itself, so that c.child == c is always True. > This makes sense on one hand, because c is also an instance of > Parent, but on the other, Child doesn't have a subclass, so > should .child be None? > > I haven't actually encountered this in any real life situation, > because it's hard to end up with collection in Django where you have > a mix of parent and child instances, so maybe it'll never be a > problem. > > One additional thing is that in one case, I know which subclasses > I'm interested in, and it'd be great to have a way to specify that a > queryset should return polymorphic results by specifying the > subclasses for the join. Something like: > > Parent.objects.all().select_subclasses('Child1','Child2') This is a dirty hack, but it came in handy for me... If you add this method to your parent class: def canonical(self): attr_name = '%s_ptr' % self._meta.module_name children_fields = [r.get_accessor_name() for r in self._meta.get_all_related_objects() if r.field.name == attr_name] for f in children_fields: try: return getattr(self, f).canonical() except models.ObjectDoesNotExist: pass return self You can then convert a queryset to a list of child classes: child_classes = [c.canonical() for c in Parent.objects.all()] Basically, canonical() tries to grab a list of descendant classes, then cycles through those until it finds one that exists. If it can't find an instance of a descendant class, it just hands back the parent since that's what you have. It's also recursive so it will traverse n- levels of inheritance. scott. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---