Reputation: 656
In this django project, there are a lot of models and we want to add a custom queryset and a manager to each using the queryset.as_manager without having to specify it in each model by hand.
All the queryset/managers are organized in a parallel structure to each model in a manager.py folder in the individual django apps.
Since the managers are a class level attribute, adding them in the init does not work and django does some pretty fancy meta programming so what's the right way to do this? Both Django 1.7 and 1.8 are acceptable. Thanks
(I get that the pythonic way is explicit better than implicit but it seems to be a a lot of crud code here so is there a Meta way of doing this.)
Upvotes: 3
Views: 2485
Reputation: 6013
You could write a factory function to create proxy models like this one:
def model_with_queryset(model_class, queryset_class):
class Proxy(model_class):
objects = queryset_class.as_manager()
class Meta:
proxy = True
app_label = model_class._meta.app_label
return Proxy
Here model_class
would be any model you want to change the queryset on.
You could then create model classes dynamically:
SomeModelWithSomeQS = model_with_queryset(SomeModel, SomeQS)
and use them as any other (proxy) model.
Upvotes: 4
Reputation: 77912
The django-way would be to use the db.signals.class_prepared
signal and draw inspiration from django.db.managers.ensure_default_manager()
to properly add the manager to the class (mainly using model.add_to_class()
to make sure the managers's contribute_to_class()
method is properly invoked). Then you'll have to write some utility function to retrieve the appropriate queryset for a given model class.
Or you could write your own custom metaclass (based on django.db.models.base.ModelBase
) and model class (using your custom metaclass) and make all your model classes inherit from it.
This being said, you'd really need to have a lot of models to even consider either of these solutions as economically valid...
Upvotes: 2