On Mon, Feb 04, 2008 at 08:32:17AM -0500, George Vilches wrote: > Since we've been using a metaclass for doing a similar task, seems > appropriate to paste it now: > > class ModelMixinBase(ModelBase): > def __new__(cls, name, bases, attrs): > new_attrs = attrs.copy() > for attr,value in cls.__dict__.iteritems(): > if isinstance(value, models.Field): > new_attrs.setdefault(attr,value) > elif attr == 'methods': > for v in value: > if callable(v): > new_attrs.setdefault(v.__name__, v) > elif isinstance(v, str): > new_attrs.setdefault(v, getattr(cls, v)) > return super(ModelMixinBase, cls).__new__(cls, name, bases, > new_attrs) > class MixinBaseA(ModelMixinBase): > common_1 = models.IntegerField() > common_2 = models.CharField(max_length=255) > class ResultModel(models.Model): > __metaclass__ = MixinBaseA > specific_1 = models.IntegerField() > The end result should give you as far as we have been able to tell a > perfectly okay Django model instance (we've been using it for months > and haven't seen any weird behavior yet). We know it does a touch more > than what yours does, but it could easily be stripped down to just be > the equivalent of what you've got above.
I see only one particular fault with this approach- if you ever add functionality to allow N inheriting parents, instead of a single line of inheritance. Django internally has a rather voodoo-rific creation_counter in the Field class namespace, that serves as an instance count for each Field derivative instantiated, and it uses that creation_counter to determine where to insert the Field derivative into the Models fields list (which maps out to the sql column ordering). If you ever try to extend your metaclass approach to allow mixing multiple parents (which makes sense, imo), the sql column ordering would be dependant on the order of imports. Aside from that, nifty approach although I think I'd try to mangle the ModelMixinBase instance so it was invokable, and then use it like so- class ResultModel(MixinBaseA(), MixinBaseB()): specific_1 = models.IntegerField() The reason I'd try that direction is due to the creation_counter voodoo- if you could slightly bastardize ModelMixinBase.__call__ so that it was able return clones of the fields (with the creation_counter incremented), it would solve the sql field order issue I mentioned above while enabling N parent inheritance. Just a thought. ~brian
pgpMlTjNEbvE4.pgp
Description: PGP signature
