views:

276

answers:

2

What i want to do is when some model use my field, it will automaticaly add custom manager to that model.

As far as i know, contibute_to_class provide such functionality

class MyCustomField(CharField):
    def contribute_to_class(self, cls, name):
        super(MyCustomField, self).contribute_to_class(cls, name)
        setattr(cls, 'custom_manager', CustomManager())

The problem is that in my custom manager i use self.model._default_manager to do queries on default manager but when i try to do it, django says AttributeError: 'NoneType' object has no attribute '_default_manager'

If i dont use contribute_to_class and write custom manager iside my model class, it works as expected. What can be the problem?

+1  A: 
class MyCustomField(CharField):
    def contribute_to_class(self, cls, name):
        super(MyCustomField, self).contribute_to_class(cls, name)
        manager = CustomManager()
        manager.model = cls
        setattr(cls, 'custom_manager', manager)
Setting manager.model manually is hacky and fragile. That is only part of what Manager.contribute_to_class does - the real solution is to ensure Manager.contribute_to_class is called properly.
Carl Meyer
+2  A: 

Managers, just like Fields, have a contribute_to_class method, and if you don't call it they won't be set up properly. The correct way to call it is by using Model.add_to_class:

class MyCustomField(CharField):
    def contribute_to_class(self, cls, name):
        super(MyCustomField, self).contribute_to_class(cls, name)
        cls.add_to_class('custom_manager', CustomManager())
Carl Meyer