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
-~----------~----~----~----~------~----~------~--~---

Reply via email to