3
votes

I am using django-tastypie to create a rest API for my webapp. I want to create classes like mentioned below without typing them all out explicitly(I have more than a 100 classes)

class CityResource(ModelResource):
    class Meta:
        queryset = City.objects.all()
class StateResource(ModelResource):
    class Meta:
        queryset = State.objects.all()
etc...

I was thinking of using metaclasses in python(my approach might be wrong but still want to solve it this way as I want to see how metaclass can help me and maybe a good way to learn it in a real life problem)

I tried this:

class ClassFactory(type):
    def __new__(cls, name, bases, dct):
        return type.__new__(cls, name, bases, dct)

for model in get_models(app):
    name = "%sResource" % model._meta.object_name
    ClassFactory(name, (ModelResource, ), {'Meta':type('Meta', (), {'queryset': model.objects.all()})})

But this gives an error:

TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

I googled up on this and everywhere it mentions about how if a class derives from 2 other classes that have two different metaclass then the class I make must have a metaclass that was derived from the two metaclasses[*].

  1. How does this error happen in my case, as I am deriving from the same class ModelResource?
  2. I am not sure I understand [*]

I might be solving this problem the wrong way, but need some pointers.

1
"(my approach might be wrong but still want to solve it this way)" I never understand this attitude. If your approach is wrong, change it. I don't have anything constructive to say here, since django often makes you do things that you wouldn't normally have to do, but don't knowingly dismiss a potential better way to do what you're doing. And yes, 100 classes sounds like madness. - Julian
My idea is to learn how metaclasses would help me here which is why I am asking this question. To primarily learn how to write metaclasses for this and if possible also learn why this approach might be wrong if at all. This is the attitude. I always thought it's fine to ask such questions atleast on SO. - zubinmehta
Also, the question has really got nothing to do with django - zubinmehta
I think you should learn how to use metaclasses when you have a problem that should be solved with a metaclass (which is exceedingly rare, and prominent Python core devs have said approaches being needed by less than 1% of Python developers). I'm not saying it's not necessary here, it may be, but it's something to keep in mind. As for what questions are appropriate for SO, I have no idea, but I should hope ones that help you write good code would be the benchmark. - Julian
I don't think you need the ClassFactory "metaclass" at all. type(name, (ModelResource, ), {...}) should return a new class that's derived from ModelResource, as you want. - AKX

1 Answers

0
votes

(Reposted from comment.)

I don't think you need the ClassFactory "metaclass" at all.

klass = type(name, (ModelResource, ), {...})

should get you a new class that's derived from ModelResource, as you want.