Michael Bayer wrote:
> 
> i think using the polymorphic_map is OK.  i downplayed its 
> existence since I felt it was confusing to people, which is 
> also the reason i made the _polymorphic_map argument to 
> mapper "private"; it was originally public.  but it seemed 
> like it was producing two ways of doing the same thing so i 
> made it private.

OK - I'll carry on using that then.

>
> <using class_mapper() function instead of class.mapper>
>

Ah - that's what I was missing. I hadn't seen the class_mapper function.
Thanks for that.

> 
> as far as having multiple "polymorphic_identity" values map 
> to the same class, i would think we could just have 
> polymorphic_identity be a list instead of a scalar.  right 
> now, if you just inserted multiple values for the same class 
> in polymorphic_map, it would *almost* work except that the 
> save() process is hardwiring the polymorphic_on column to the 
> single polymorphic_identity value no matter what its set to.
> 
> so attached is an untested patch which accepts either a 
> scalar or a list value for polymorphic_identity, and if its a 
> list then instances need their "polymorphic_on" attribute set 
> to a valid entry before flushing.  try this out and see if it 
> does what you need, and i can easily enough add this to the 
> trunk to be available in the next release (though id need to 
> write some tests also).
> 

I think this would definitely be a useful feature, and in fact I was
originally going to attempt (or at least suggest!) something like that
myself. I'll try the patch and let you know how well it works.

However, I still have a situation where I would like to be able to use a
default class for unknown types. I don't want to hard-code all the
possible options up-front - only the ones that I actually want to treat
specially. I've been playing around with some different options, and
this is what I've ended up with:

class EmployeeMeta(type):
    def __call__(cls, kind, _fix_class=True, **kwargs):
        if not _fix_class:
            return type.__call__(cls, kind=kind, **kwargs)
        cls = get_employee_class(kind)
        return cls(kind=kind, _fix_class=False, **kwargs)

def get_employee_class(kind):
    if kind == 'manager':
        return Manager
    else:
        return Employee

class Employee(object):
    __metaclass__ = EmployeeMeta

class Manager(Employee):
    pass


class EmployeeMapperExtension(sa.MapperExtension):
    def create_instance(self, mapper, selectcontext, row, class_):
        cls = get_employee_class(row[employee_table.c.kind])
        if class_ != cls:
            return sa.class_mapper(cls)._instance(selectcontext, row)
        return sa.EXT_PASS

assign_mapper(ctx,
              Employee, employee_table,
              extension=EmployeeMapperExtension())
assign_mapper(ctx,
              Manager,
              inherits=Employee.mapper)


This seems to do the right thing - Manager instances get created for
managers, but any other row becomes an Employee. To add a subclass for
another row type, I just need to adapt the get_employee_class function
and add another call to assign_mapper. With a bit more work in the
metaclass, it could all be done with a special attribute in the
subclass.

The only thing I'm not sure about is the mapper extension - is it OK to
call the mapper._instance method, or is there a better way to do this?

Thanks again,

Simon


--~--~---------~--~----~------------~-------~--~----~
 You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Attachment: inheritance_test.py
Description: inheritance_test.py

Reply via email to