get_manager short ut function proposal

59 views
Skip to first unread message

Ramez Ashraf

unread,
Dec 19, 2022, 5:51:50 PM12/19/22
to Django developers (Contributions to Django itself)
Hello everyone, 

I want to propose a helper function
`get_manager(parent_manager=None, *args, **kwargs)` 

A shortcut to return a manager, *args & **kwargs are passed to the manager .filter()
pass parent_manager to customize the parent manager, defaults to ``Manager``.

it can be used like this 

from django.db.models import get_manager

class Person(models.Model):
    # ...
    authors = models.get_manager(role='A')
    editors = models.get_manager(role='E')
    special = get_manager(~Q(name="Roald Dahl"), role='E')
    manager_with_counts = get_manager(parent_manager=PollManager, name="Roald Dahl")

Instead of the current 

class AuthorManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(role='A')

class EditorManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(role='E')

class Person(models.Model):
    people = models.Manager()
    authors = AuthorManager()
    editors = EditorManager()
   ...

The first is more readable and nicer .. yeah ?
Code is working and ready at  github ,  

Do i get +1(s) to move forward and create a ticket ? 


Adam Johnson

unread,
Dec 31, 2022, 5:41:27 AM12/31/22
to django-d...@googlegroups.com
Your proposal is quite niche: it only shortens the creation of a Manager class when you need to add a single filter() call. The function seems like it might be a useful helper within a project, if you use many such managers. But custom managers might use any queryset methods, or other logic. I've often used a custom manager to add annotate() and prefetch_related() calls.

So, I think your shortcut is a smart addition for your project, but perhaps not suitable for Django itself. I think it's worth sharing in a blog post though!

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/f0e4367d-8a7e-48da-b78c-35036015212fn%40googlegroups.com.

Ramez Ashraf

unread,
Jan 1, 2023, 9:34:08 AM1/1/23
to django-d...@googlegroups.com
Hello Adam 
Happy new year!

Thank you for the feedback, really appreciate it.
I thought the same like you at first, a cool function in my project (which is indeed the case)
One thing that gave me more incentive is the documentation code example.
IMO, i can see how shorter (and more readable) it would be with the proposed shortcut.
In fact it's indeed simple and doesn't offer the full support a real declared custom manager class would do. It's intended to be something like get_object_or_404.

Interested or do you think the function can be enhanced it to make more useable for your everyday other cases ?



You received this message because you are subscribed to a topic in the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-developers/CISeAzzESHA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/CAMyDDM0Jk%3DYsXQVRydaanmg%3DP_wMMmg%2B4uPETSvEXs3jFgCB%2BQ%40mail.gmail.com.

Shai Berger

unread,
Jan 1, 2023, 12:01:08 PM1/1/23
to Ramez Ashraf, django-d...@googlegroups.com
On Sun, 1 Jan 2023 16:33:45 +0200
Ramez Ashraf <ramez...@gmail.com> wrote:

>
> Interested or do you think the function can be enhanced it to make
> more useable for your everyday other cases ?
>

This is half-baked, just a thought, but maybe you can take it some
place interesting:

Imagine a class that "collects" calls for later execution. Something
like (this exactly won't work, details below):

from functools import partialmethod
from django.db.models import QuerySet as QSet

class QS:
def __init__(self):
self._calls = []
def filter(self, *args, **kw):
self._calls.append(
partialmethod(QSet.filter, *args, **kw)
)
return self
def annotate(*args, **kw):
# ... (same idea)
# ... other relevant methods,
def __call__(self, qset):
for call in self._calls:
qset = apply(call, qset)
return qset

This won't work, I think, because partialmethod isn't supposed to work
quite this way, and the "apply" in the last line isn't defined. But
with this (fixed) already you could, I think, do something like

def qset_manager(qs: QS) -> Manager
class CustomManager(models.Manager):
def get_queryset(self):
orig = super().get_queryset()
return qs(orig)
return CustomManager()

And then, in your model,

class Person(models.Model):
...
authors = qset_manager(QS().filter(role="A"))

and now the "make a manager with a modified queryset" pattern is
shortened in a general way.

As I said, just a half-baked thought. There's problems here to solve,
and many improvements to make.

HTH,
Shai.

Ramez Ashraf

unread,
Jan 1, 2023, 12:21:33 PM1/1/23
to Shai Berger, django-d...@googlegroups.com
Mmmm I believe what you shared Shai is very sophisticated than what is proposed.
The proposal is a shortcut function for with ability to have a custom parent for more usability for an everyday use , like what's in the documentation about managers.

My proposal is *not* a new way to write managers . This can be your or someone else's fully baked idea.

With respect.
Reply all
Reply to author
Forward
0 new messages