A `models.Manager` subclass that helps to remove some of the boilerplate involved in creating managers from certain queries. Usually, a manager would be created by doing this:
class MyManager(models.Manager):
def get_query_set(self):
return super(MyManager, self).get_query_set().filter(query=blah)
Other managers may return other query sets, but this is especially useful as one may define queries on a table which would be used a lot. Since the only part that ever changes is the `query=blah` set of keyword arguments, I decided to abstract that into a class which, besides taking the repetition out of manager definition, allows them to be and'd and or'd in a manner similar to the `Q` objects used for complex database queries.
`CustomQueryManager` instances may be defined in one of two ways. The first, more laborious but reusable manner, is to subclass it, like so:
class MyManager(CustomQueryManager):
query = Q(some=query)
Then, `MyManager` is instantiated with no arguments on a model, like normal managers. This allows a query to be reused without extra typing and copying, and keeps code DRY.
Another way to do this is to pass a `Q` object to the `__init__` method of the `CustomQueryManager` class itself, on the model. This would be done like so:
class MyModel(models.Model):
field1 = models.CharField(maxlength=100)
field2 = models.PositiveIntegerField()
my_mgr = CustomQueryManager(Q(field1='Hello, World'))
This should mainly be used when a query is only used once, on a particular model. Either way, the definition of `__and__` and `__or__` methods on the `CustomQueryManager` class allow the use of the `&` and `|` operators on instances of the manager and on queries. For example:
class Booking(models.Model):
start_date = models.DateField()
end_date = models.DateField()
public = models.BooleanField()
confirmed = models.BooleanField()
public_bookings = CustomQueryManager(Q(public=True))
private_bookings = public_bookings.not_()
confirmed_bookings = CustomQueryManager(Q(confirmed=True))
public_confirmed = public_bookings & confirmed_bookings
public_unconfirmed = public_bookings & confirmed_bookings.not_()
public_or_confirmed = public_bookings | confirmed_bookings
public_past = public_bookings & Q(end_date__lt=models.LazyDate())
public_present = public_bookings & Q(start_date__lte=models.LazyDate(), end_date__gte=models.LazyDate())
public_future = public_bookings & Q(start_date__gt=models.LazyDate())
As you can see, `CustomQueryManager` instances can be manipulated much like `Q` objects, including combination, via `&` (and) and `|` (or), with other managers (currently only other `CustomQueryManager` instances) and even `Q` objects. This makes it easy to define a set of prepared queries on the set of data represented by a model, and removes a lot of the boilerplate of usual manager definition.
- models
- q
- manager
- query
- custom