简体   繁体   中英

Django get all base class objects that their derived class has a mixin

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))

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM