Reputation: 2308
I have models that look something like this:
class SomeModel(model.Model):
pass
class Base(models.Model):
field1 = ...
class Mixin1(models.Model):
some_model = models.ForeignKey('SomeModel', on_delete=models.CASCADE)
class Meta:
abstract = True
class Derive1(Base, Mixin1):
field2 = ...
class Derive2(Base, Mixin1):
field3 = ...
class Derive3(Base):
field4 = ...
Now I want to be able to get all objects that derive from Base
and Mixin1
, without explicitly listing all classes that use Mixin1
.
Something like:
Base.objects.filter(some_model=X)
Why this doesn't work I understand, but how to actually make it work I do not know.
Solution: Thanks to valentjedi's answer I got to a working solution. I am posting it here in case it will help someone one day.
On top of wanting all the results together, I also wanted them sorted by a date field in Base and the ability to filter them freely. So I created in Mixin1
the function:
@staticmethod
def get_mixin1_objects(some_model, q_filter=None):
mixin_models = set(Mixin1.__subclasses__()) & set(Base.__subclasses__())
results = []
for mdl in mixin_models:
apply_filter = Q(some_model=some_model)
if q_filter is not None:
apply_filter &= q_filter
results.append(list(mdl.objects.filter(apply_filter).order_by('date').all()))
# Merge sort all the events
return list(heapq.merge(*results))
While adding to Base the method:
def __gt__(self, other):
return self.date > other.date
Thus I can apply filters however I like, and can get order_by
a constant field results (which suffices my current needs).
Example of usage:
lst = Mixinq.get_mixin1_objects(some_model_instance, q_filter=~Q(some_field_in_base=some_value))
Upvotes: 2
Views: 1505
Reputation: 6316
I might not understand your question clearly, but you can use __subclasses__
magic method for something like this:
>>> set(Mixin1.__subclasses__()) & set(Base.__subclasses__())
{Derive2, Derive1}
Then you can filter those models and do whatever you want to them.
Upvotes: 5