[Solved]-Creating instances of Django proxy models from their base class

15👍

I haven’t found a “clean” or “elegant” way to do this. When I ran into this problem I solved it by cheating Python a little bit.

class Check(models.Model):
    check_type = models.CharField(max_length=10, editable=False)
    type = models.CharField(max_length=10, null=True, choices=TYPES)
    method = models.CharField(max_length=25, choices=METHODS)
    'More fields.'

    def __init__(self, *args, **kwargs):
        super(Check, self).__init__(*args, **kwargs)
        if self.check_type:
            map = {'TypeA': Check_A,
                'TypeB': Check_B,
                'TypeC': Check_C}
            self.__class__ = map.get(self.check_type, Check)

    def run(self):
        'Do the normal stuff'
        pass


class Check_A(Check):
    class Meta:
        proxy = True

    def run(self):
        'Do something different'
        pass

class Check_B(Check):
    class Meta:
        proxy = True

    def run(self):
        'Do something different'
        pass


class Check_C(Check):
    class Meta:
        proxy = True

    def run(self):
        'Do something different'
        pass

It’s not really clean but it was the easiest hack to find which solved my problem.

Maybe this is helps you, maybe it doesn’t.

I’m also hoping someone else has a more pythonic solution to this problem since I’m counting the days till this method fails and comes back to haunt me..

👤EWit

7👍

This is a great approach and I don’t particularly see it as a cheat. Here is IMHO some enhancements to the __init__ function so it doesn’t has to change when you add more classes.

def __init__(self, *args, **kwargs):
    super(Analysis, self).__init__(*args, **kwargs)
    if not self.__type and type(self) == Analysis:
        raise Exception("We should never create a base Analysis object. Please create a child proxy class instead.")

    for _class in Analysis.__subclasses__():
        if self.check_type == _class.__name__:
            self.__class__ = _class
            break

def save(self, **kwargs):
    self.check_type = self.__class__.__name__
    super(Analysis, self).save(**kwargs)

Hope this helps!

👤Hassek

Leave a comment