Change manager for Model.objects with a decorator

This is an interesting, well-described question on StackOverflow which hasn’t received any answers. Would anyone here be able to help myself and the original author in finding a solution?

Much appreciated!

Hi Addison,

I have a few questions around the purpose of the change. Is your goal to have a default manager for your models? Do you want to override Django’s system models? Would also like this to apply to third party app’s models?

-Tim

Hi Tim,

Yes I would like to override the default objects manager so that built-in fixture commands like loaddata and dumpdata (which use the default manager) will work with natural keys. Although I could define the manager and natural_key() methods on all my models manually as shown in the docs, I saw a neat DRY solution on Github which seemed really elegant. The problem is the author hasn’t been able to update their code to work with Django >= 1.10 due to the issue above. I’m looking to patch their solution so that I can use the @with_natural_key('field') decorator for my models

Just a comment about this: remember that objects is a pretty arbitrary name really. It’s the django default name of course, but you can have multiple managers for a model, so you could define for example objects, sharpobjects and bluntobjects as 3 different model managers and use them accordingly.

@michjnich That’s true, but in order to have the built-in dumpdata and loaddata commands pick up a custom manager, I think either

  1. It needs to be under the objects attribute
  2. The model class _default_manager needs to point to the custom manager. The docs say this can be done through Meta.default_manager_name, but I find that adding meta in my decorator have any effect

@CodenameTim Any more thoughts given the additional context around using DRY natural keys with built-in management commands?

What I’ve done in the past is to create a custom manager that looks at a property on the class for the paths to fields that make up the natural key. Then the base class uses that property to expose the actual components necessary for the various functionality. All models then needed to use that custom manager or inherit from a custom class that uses the manager.