1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
Managers & Querysets
====================
Using a Custom Manager
----------------------
A nice feature of Django is the possibility to define one's own custom object managers.
This is fully supported with :pypi:`django-polymorphic`. For creating a custom polymorphic
manager class, just derive your manager from :class:`~polymorphic.managers.PolymorphicManager`
instead of :class:`~django.db.models.Manager`. As with vanilla Django, in your model class, you
should explicitly add the default manager first, and then your custom manager:
.. code-block:: python
from polymorphic.models import PolymorphicModel
from polymorphic.managers import PolymorphicManager
class TimeOrderedManager(PolymorphicManager):
def get_queryset(self):
qs = super(TimeOrderedManager,self).get_queryset()
return qs.order_by('-start_date')
def most_recent(self):
qs = self.get_queryset() # get my ordered queryset
return qs[:10] # limit => get ten most recent entries
class Project(PolymorphicModel):
objects = PolymorphicManager() # add the default polymorphic manager first
objects_ordered = TimeOrderedManager() # then add your own manager
start_date = DateTimeField() # project start is this date/time
The first manager defined (:attr:`~django.db.models.Model.objects` in the example) is used by Django
as automatic manager for several purposes, including accessing related objects. It must not filter
objects and it's safest to use the plain :class:`~polymorphic.managers.PolymorphicManager` here.
Manager Inheritance
-------------------
Polymorphic models inherit/propagate all managers from their base models, as long as these are
polymorphic. This means that all managers defined in polymorphic base models continue to work as
expected in models inheriting from this base model:
.. code-block:: python
from polymorphic.models import PolymorphicModel
from polymorphic.managers import PolymorphicManager
class TimeOrderedManager(PolymorphicManager):
def get_queryset(self):
qs = super(TimeOrderedManager,self).get_queryset()
return qs.order_by('-start_date')
def most_recent(self):
qs = self.get_queryset() # get my ordered queryset
return qs[:10] # limit => get ten most recent entries
class Project(PolymorphicModel):
objects = PolymorphicManager() # add the default polymorphic manager first
objects_ordered = TimeOrderedManager() # then add your own manager
start_date = DateTimeField() # project start is this date/time
class ArtProject(Project): # inherit from Project, inheriting its fields and managers
artist = models.CharField(max_length=30)
ArtProject inherited the managers ``objects`` and ``objects_ordered`` from Project.
``ArtProject.objects_ordered.all()`` will return all art projects ordered regarding their start time
and ``ArtProject.objects_ordered.most_recent()`` will return the ten most recent art projects.
Using a Custom Queryset Class
-----------------------------
The :class:`~polymorphic.managers.PolymorphicManager` class accepts one initialization argument,
which is the queryset class the manager should use. Just as with vanilla Django, you may define your
own custom queryset classes. Just use :class:`~polymorphic.managers.PolymorphicQuerySet` instead of
Django's :class:`~django.db.models.query.QuerySet` as the base class:
.. code-block:: python
from polymorphic.models import PolymorphicModel
from polymorphic.managers import PolymorphicManager
from polymorphic.query import PolymorphicQuerySet
class MyQuerySet(PolymorphicQuerySet):
def my_queryset_method(self):
...
class MyModel(PolymorphicModel):
my_objects = PolymorphicManager.from_queryset(MyQuerySet)()
...
If you do not wish to extend from a custom :class:`~polymorphic.managers.PolymorphicManager` you
may also prefer the :meth:`~polymorphic.managers.PolymorphicQuerySet.as_manager`
shortcut:
.. code-block:: python
from polymorphic.models import PolymorphicModel
from polymorphic.query import PolymorphicQuerySet
class MyQuerySet(PolymorphicQuerySet):
def my_queryset_method(self):
...
class MyModel(PolymorphicModel):
my_objects = MyQuerySet.as_manager()
...
For further discussion see `this topic on the Q&A page
<https://github.com/jazzband/django-polymorphic/discussions/696#discussioncomment-15223661>`_.
|