Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

For ticket #20625 to allow defining chainable QuerySet on custom model managers. #1284

Closed
wants to merge 1 commit into from

2 participants

@danielsokolowski

Ticket #20625 - https://code.djangoproject.com/ticket/20625 allows for new functionality as follows:

class OfferManager(models.Manager):
    """ Example of a chainable custom query set """

    ...

    QUERYSET_PUBLIC_KWARGS = {'status__gte': STATUS_ENABLED}
    QUERYSET_ACTIVE_KWARGS = {'status': STATUS_ENABLED}

    ...

    def public(self):
        """ Returns all entries accessible through front end site"""
        return self.all().filter(...)
    public.chainable = True     # instructs to dynamically tranplat this method onto
                                # returned QuerySet as <queryset>.public(...) 
                                # effectively providing chainable custom QuerySets

    def active(self):
        """ Returns offers that are open to negotiation """
        return self.public().filter(**OfferManager.QUERYSET_ACTIVE_KWARGS)
                                    # an example of how to reffer to OfferManager
                                    # constants as 'self' context changes
    active.chainable = True
    ...
@timgraham
Owner

I think we're going with the approach in #1328

@timgraham timgraham closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 19, 2013
  1. Working patch for ticket #20625 to allow defining chainable QuerySet …

    Daniel Sokolowski authored
    …on custom model managers.
This page is out of date. Refresh to see the latest.
Showing with 19 additions and 2 deletions.
  1. +19 −2 django/db/models/manager.py
View
21 django/db/models/manager.py
@@ -121,9 +121,26 @@ def db(self):
#######################
def get_queryset(self):
- """Returns a new QuerySet object. Subclasses can override this method
- to easily customize the behavior of the Manager.
"""
+ Returns a new QuerySet object. Subclasses can override this method
+ to customize the behavior of the Manager.
+
+ Methods that have a 'chainable' attribute set to 'True' are copied
+ onto the retruned 'QuerySet'; this allows for the proxies to be
+ chainable without the need to duplicate proxies in a custom QuerySet.
+ """
+ chainable_queryset_list = [(m, getattr(self, m)) for m in dir(self) if not m.startswith('__') \
+ and callable(getattr(self, m)) and hasattr(getattr(self, m), 'chainable') \
+ and getattr(self, m).chainable == True]
+ # create a dynamically defined QuerySet if needed otherwise return a plain QuerySet for backward compatibility
+ if len(chainable_queryset_list) > 0:
+ class QuerySetDynamicallyCreated(QuerySet):
+ pass
+ for method_name, method in chainable_queryset_list:
+ setattr(QuerySetDynamicallyCreated, method_name, method)
+ QuerySetDynamicallyCreated.__name__ = '{0}QuerySetDynamicallyCreated'.format(self.model.__name__)
+ return QuerySetDynamicallyCreated(self.model, using=self._db)
+
return QuerySet(self.model, using=self._db)
def none(self):
Something went wrong with that request. Please try again.