Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I spent a while trying to come up with a way to build a nice factory to do this, but I'm running into a lot of problems with that.</p> <p>The best I can suggest to you is to chain your inheritance. It's not very generic, so I'm not sure how useful it is, but all you would have to do is:</p> <pre><code>class GlobalMixin(DeleteMixin): is_global = models.BooleanField(default=True) objects = GlobalManager() class Meta: abstract = True class GlobalManager(DeleteManager): def globals(self): return self.get_query_set().filter(is_global=1) </code></pre> <p>If you want something more generic, the best I can come up with is to define a base <code>Mixin</code> and <code>Manager</code> that redefines <code>get_query_set()</code> (I'm assuming you only want to do this once; things get pretty complicated otherwise) and then pass a list of fields you'd want added via <code>Mixin</code>s.</p> <p>It would look something like this (not tested at all):</p> <pre><code>class DeleteMixin(models.Model): deleted = models.BooleanField(default=False) class Meta: abstract = True def create_mixin(base_mixin, **kwargs): class wrapper(base_mixin): class Meta: abstract = True for k in kwargs.keys(): setattr(wrapper, k, kwargs[k]) return wrapper class DeleteManager(models.Manager): def get_query_set(self): return super(DeleteManager, self).get_query_set().filter(deleted=False) def create_manager(base_manager, **kwargs): class wrapper(base_manager): pass for k in kwargs.keys(): setattr(wrapper, k, kwargs[k]) return wrapper </code></pre> <p>Ok, so this is ugly, but what does it get you? Essentially, it's the same solution, but much more dynamic, and a little more DRY, though more complex to read.</p> <p>First you create your manager dynamically:</p> <pre><code>def globals(inst): return inst.get_query_set().filter(is_global=1) GlobalDeleteManager = create_manager(DeleteManager, globals=globals) </code></pre> <p>This creates a new manager which is a subclass of <code>DeleteManager</code> and has a method called <code>globals</code>.</p> <p>Next, you create your mixin model:</p> <pre><code>GlobalDeleteMixin = create_mixin(DeleteMixin, is_global=models.BooleanField(default=False), objects = GlobalDeleteManager()) </code></pre> <p>Like I said, it's ugly. But it means you don't have to redefine <code>globals()</code>. If you want a different type of manager to have <code>globals()</code>, you just call <code>create_manager</code> again with a different base. And you can add as many new methods as you like. Same for the manager, you just keep adding new functions that will return different querysets.</p> <p>So, is this really practical? Maybe not. This answer is more an exercise in (ab)using Python's flexibility. I haven't tried using this, though I do use some of the underlying principals of dynamically extending classes to make things easier to access.</p> <p>Let me know if anything is unclear and I'll update the answer.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload