12

I'm using django-tastypie and I need to create classes like this from my django models:

class MyModelResource(ModelResource):
    class Meta:
        queryset = MyModel.objects.all()
        allowed_methods = ['get']

Since I have a lot of models in my django app I don't want to repeat myself, and use type() function instead to create all that resource classes. The problem is I don't know how to deal with this inner "Meta" class.

Can you give me an example of how to dynamically create a class with inner class using type()?

1 Answer 1

16
class MyModel(object) : pass
modelClass = MyModel()

class ModelResource(object):
    def mymethod(self):
        print('got here')

Meta = type('Meta', (object, ), {'allowed_methods': ['get']})

def add_mymethod(cls):
    def mymethod(self):
        super(cls, self).mymethod()
    cls.mymethod = mymethod
    return cls

name = modelClass.__class__.__name__ + "Resource"
MyModelResource = add_mymethod(type(name, (ModelResource, ),
                                    {'Meta':Meta, }))

print(MyModelResource.Meta)
# <class '__main__.Meta'>

m = MyModelResource()
m.mymethod()
# got here

The inner class, Meta, is just another attribute as far as MyModelResource is concerned.


Methods are also just attributes as far as MyModelResource is concerned. Actually, you define a function in MyModelResource.__dict__, and the Python attribute lookup mechanism causes inst.mymethod to return a bound method.

There is no problem referring to MyModelResource in the super call

super(MyModelResource, self).mymethod()

before MyModelResource is defined, because name lookups are performed at run time, not at the time mymethod is defined.


You are absolutely correct that

super(self.__class_, self).mymethod()

is wrong. This will spoil all that is good about super. If MyModelResource were to be subclassed, and an instance of the subclass were to call mymethod, then Python would fall into an infinite loop.

Sign up to request clarification or add additional context in comments.

3 Comments

This is correct answer. Now, what if I have to define method that calls super() inside? I want to avoid writing super(self.__class__, self) because apparently is not a good idea...
the problem is I don't know name of the class in the moment of defining method. In my case creation of class looks like this: type(modelClass.__class__.__name__ + "Resource",(ModelResource, ), {"Meta"... So I cant refer to it by name in the method.
Okay, so mymethod can not be defined until after MyModelResource is defined. In that case, use a class decorator. I've added the class decorator, add_mymethod as an example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.