Created
April 21, 2009 11:20
-
-
Save zacharyvoase/99083 to your computer and use it in GitHub Desktop.
Django Managers for pre-defined queries.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
Managers for pre-defined queries. | |
Example:: | |
from django.db import models | |
from qmanager import QManager | |
class MyModel(models.Model): | |
# Fields | |
... | |
is_hidden = models.BooleanField() | |
... | |
# Managers | |
objects = models.Manager() | |
public = QManager(models.Q(is_hidden=False)) | |
hidden = ~public # NOT public. | |
QManagers support combination via ``&`` and ``|``, with each other and also with | |
instances of ``django.db.models.Q`` (i.e. query objects). | |
""" | |
from django.db import models | |
def metaclass(cls): | |
if not issubclass(cls, object): | |
raise TypeError('Class %r does not support metaclasses.' % (cls,)) | |
return getattr(cls, '__metaclass__', type) | |
def get_query(obj): | |
if (isinstance(obj, QManager) or | |
(isinstance(obj, type) and issubclass(obj, QManager)) or | |
hasattr(obj, 'query')): | |
return obj.query | |
elif isinstance(obj, models.Q): | |
return obj | |
raise TypeError('Object %r is not a QManager or Query object.' % (obj,)) | |
class QManagerMeta(metaclass(models.Manager)): | |
def __call__(cls, *args): | |
if args: | |
return cls.with_query(*args)() | |
return super(QManagerMeta, cls).__call__() | |
def with_query(cls, query): | |
return type(cls.__name__, (cls,), | |
{'query': query, '__module__': cls.__module__}) | |
class QManager(models.Manager): | |
__metaclass__ = QManagerMeta | |
query = models.Q() | |
def __and__(self, other): | |
return type(self)(self.query & get_query(other)) | |
def __or__(self, other): | |
return type(self)(self.query | get_query(other)) | |
def __invert__(self): | |
return type(self)(~self.query) | |
def get_query_set(self): | |
return super(QManager, self).get_query_set().filter(self.query) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment