You are on page 1of 5

Docs Model Managers

Model Managers
InheritanceManager
This manager (contributed by Jeff Elmore) should be attached to a base model class in a model-inheritance tree. It allows queries on that base model to return heterogenous results of the actual proper subtypes, without any additional queries. For instance, if you have a want to query all Places:
P l a c e

model with subclasses

R e s t a u r a n t

and

B a r , you may

n e a r b y _ p l a c e s=P l a c e . o b j e c t s . f i l t e r ( l o c a t i o n = ' h e r e ' )

But when you iterate over objects that are really any
Q u e r y S e t

n e a r b y _ p l a c e s , youll get only P l a c e

instances back, even for to or


B a r: I n h e r i t a n c e M a n a g e r R e s t a u r a n t

R e s t a u r a n t

or

B a r . If you attach an I n h e r i t a n c e M a n a g e r

P l a c e , you can just call the s e l e c t _ s u b c l a s s e s ( )

method on the

from it, and the resulting objects will be instances of

or

f r o mm o d e l _ u t i l s . m a n a g e r si m p o r tI n h e r i t a n c e M a n a g e r c l a s sP l a c e ( m o d e l s . M o d e l ) : #. . . o b j e c t s=I n h e r i t a n c e M a n a g e r ( ) c l a s sR e s t a u r a n t ( P l a c e ) : #. . . c l a s sB a r ( P l a c e ) : #. . . n e a r b y _ p l a c e s=P l a c e . o b j e c t s . f i l t e r ( l o c a t i o n = ' h e r e ' ) . s e l e c t _ s u b c l a s s e s ( ) f o rp l a c ei nn e a r b y _ p l a c e s : #" p l a c e "w i l la u t o m a t i c a l l yb ea ni n s t a n c eo fP l a c e ,R e s t a u r a n t ,o rB a r

The database query performed will have an extra join for each subclass; if you want to reduce the number of joins and you only need particular subclasses to be returned as their actual type, you can pass subclass names to s e l e c t _ s u b c l a s s e s ( ) , much like the

built-in

s e l e c t _ r e l a t e d ( )

method:

n e a r b y _ p l a c e s=P l a c e . o b j e c t s . s e l e c t _ s u b c l a s s e s ( " r e s t a u r a n t " ) #r e s t a u r a n t sw i l lb eR e s t a u r a n ti n s t a n c e s ,b a r sw i l ls t i l lb eP l a c ei n s t a n c e s n e a r b y _ p l a c e s=P l a c e . o b j e c t s . s e l e c t _ s u b c l a s s e s ( " r e s t a u r a n t " ," b a r " ) #a l lP l a c e sw i l lb ec o n v e r t e dt oR e s t a u r a n ta n dB a ri n s t a n c e s .

It is also possible to use the subclasses themselves as arguments to leaving it to calculate the relationship for you:

s e l e c t _ s u b c l a s s e s,

n e a r b y _ p l a c e s=P l a c e . o b j e c t s . s e l e c t _ s u b c l a s s e s ( R e s t a u r a n t ) #r e s t a u r a n t sw i l lb eR e s t a u r a n ti n s t a n c e s ,b a r sw i l ls t i l lb eP l a c ei n s t a n c e s n e a r b y _ p l a c e s=P l a c e . o b j e c t s . s e l e c t _ s u b c l a s s e s ( R e s t a u r a n t ,B a r ) #a l lP l a c e sw i l lb ec o n v e r t e dt oR e s t a u r a n ta n dB a ri n s t a n c e s .

It is even possible to mix and match the two:

n e a r b y _ p l a c e s=P l a c e . o b j e c t s . s e l e c t _ s u b c l a s s e s ( R e s t a u r a n t ," b a r " ) #a l lP l a c e sw i l lb ec o n v e r t e dt oR e s t a u r a n ta n dB a ri n s t a n c e s .

I n h e r i t a n c e M a n a g e r

also provides a subclass-fetching alternative to the

g e t ( )

method:

p l a c e=P l a c e . o b j e c t s . g e t _ s u b c l a s s ( i d = s o m e _ i d ) #" p l a c e "w i l la u t o m a t i c a l l yb ea ni n s t a n c eo fP l a c e ,R e s t a u r a n t ,o rB a r

If you dont explicitly call


I n h e r i t a n c e M a n a g e r

s e l e c t _ s u b c l a s s e s ( )

or

g e t _ s u b c l a s s ( ) , an M a n a g e r ; so its safe to use as your

behaves identically to a normal

default manager for the model. Note Due to Django bug #16572, on Django versions prior to 1.6
I n h e r i t a n c e M a n a g e r

only

supports a single level of model inheritance; it wont work for grandchild models.

QueryManager

Many custom model managers do nothing more than return a QuerySet that is filtered in some way. boilerplate:
Q u e r y M a n a g e r

allows you to express this pattern with a minimum of

f r o md j a n g o . d bi m p o r tm o d e l s f r o mm o d e l _ u t i l s . m a n a g e r si m p o r tQ u e r y M a n a g e r c l a s sP o s t ( m o d e l s . M o d e l ) : . . . p u b l i s h e d=m o d e l s . B o o l e a n F i e l d ( ) p u b _ d a t e=m o d e l s . D a t e F i e l d ( ) . . . o b j e c t s=m o d e l s . M a n a g e r ( ) p u b l i c=Q u e r y M a n a g e r ( p u b l i s h e d = T r u e ) . o r d e r _ b y ( ' p u b _ d a t e ' )

The kwargs passed to

Q u e r y M a n a g e r Q

will be passed as-is to the


Q u e r y M a n a g e r Q u e r y S e t

Q u e r y S e t . f i l t e r ( )

method. You can also pass a


Q u e r y M a n a g e r

object to

to express more complex returned by the (this is not


Q u e r y M a n a g e r

conditions. Note that you can set the ordering of the by chaining a call to
v: latest
. o r d e r _ b y ( )

on the

required).
Read the Docs

PassThroughManager
A common gotcha when defining methods on a custom manager class is that those same methods are not automatically also available on the QuerySets returned by that manager, so are not chainable. This can be counterintuitive, as most of the public QuerySet API is mirrored on managers. It is possible to create a custom Manager that returns QuerySets that have the same additional methods, but this requires boilerplate code. The
P a s s T h r o u g h M a n a g e r

class (contributed by Paul McLanahan) removes this

boilerplate. To use
P a s s T h r o u g h M a n a g e r , rather than defining a custom manager with additional Q u e r y S e t

methods, define a custom pass that custom


Q u e r y S e t

subclass with the additional methods you want, and


P a s s T h r o u g h M a n a g e r . f o r _ q u e r y s e t _ c l a s s ( )

subclass to the

class

method. The returned the manager:

P a s s T h r o u g h M a n a g e r

subclass will always return instances of your directly on

Q u e r y S e t , and you can also call methods of your custom Q u e r y S e t

f r o md a t e t i m ei m p o r td a t e t i m e f r o md j a n g o . d bi m p o r tm o d e l s f r o md j a n g o . d b . m o d e l s . q u e r yi m p o r tQ u e r y S e t f r o mm o d e l _ u t i l s . m a n a g e r si m p o r tP a s s T h r o u g h M a n a g e r c l a s sP o s t Q u e r y S e t ( Q u e r y S e t ) : d e fb y _ a u t h o r ( s e l f ,u s e r ) : r e t u r ns e l f . f i l t e r ( u s e r = u s e r ) d e fp u b l i s h e d ( s e l f ) : r e t u r ns e l f . f i l t e r ( p u b l i s h e d _ _ l t e = d a t e t i m e . n o w ( ) ) d e fu n p u b l i s h e d ( s e l f ) : r e t u r ns e l f . f i l t e r ( p u b l i s h e d _ _ g t e = d a t e t i m e . n o w ( ) )

c l a s sP o s t ( m o d e l s . M o d e l ) : u s e r=m o d e l s . F o r e i g n K e y ( U s e r ) p u b l i s h e d=m o d e l s . D a t e T i m e F i e l d ( ) o b j e c t s=P a s s T h r o u g h M a n a g e r . f o r _ q u e r y s e t _ c l a s s ( P o s t Q u e r y S e t ) ( ) P o s t . o b j e c t s . p u b l i s h e d ( ) P o s t . o b j e c t s . b y _ a u t h o r ( u s e r = r e q u e s t . u s e r ) . u n p u b l i s h e d ( )

Mixins
Each of the above manager classes has a corresponding mixin that can be used to add functionality to any manager. For example, to create a GeoDjango G e o M a n a g e r that includes pass through functionality, you can write the following code:

f r o md j a n g o . c o n t r i b . g i s . d bi m p o r tm o d e l s f r o md j a n g o . c o n t r i b . g i s . d b . m o d e l s . q u e r yi m p o r tG e o Q u e r y S e t f r o mm o d e l _ u t i l s . m a n a g e r si m p o r tP a s s T h r o u g h M a n a g e r M i x i n c l a s sP a s s T h r o u g h G e o M a n a g e r ( P a s s T h r o u g h M a n a g e r M i x i n ,m o d e l s . G e o M a n a g e r ) : p a s s c l a s sL o c a t i o n Q u e r y S e t ( G e o Q u e r y S e t ) : d e fw i t h i n _ b o u n d a r y ( s e l f ,g e o m ) : r e t u r ns e l f . f i l t e r ( p o i n t _ _ w i t h i n = g e o m ) d e fp u b l i c ( s e l f ) : r e t u r ns e l f . f i l t e r ( p u b l i c = T r u e ) c l a s sL o c a t i o n ( m o d e l s . M o d e l ) : p o i n t =m o d e l s . P o i n t F i e l d ( ) p u b l i c=m o d e l s . B o o l e a n F i e l d ( d e f a u l t = T r u e ) o b j e c t s=P a s s T h r o u g h G e o M a n a g e r . f o r _ q u e r y s e t _ c l a s s ( L o c a t i o n Q u e r y S e t ) ( ) L o c a t i o n . o b j e c t s . p u b l i c ( ) L o c a t i o n . o b j e c t s . w i t h i n _ b o u n d a r y ( g e o m = g e o m ) L o c a t i o n . o b j e c t s . w i t h i n _ b o u n d a r y ( g e o m = g e o m ) . p u b l i c ( )

Now you have a pass through manager that can also take advantage of GeoDjangos spatial lookups. You can similarly add additional functionality to any manager by composing that manager with I n h e r i t a n c e M a n a g e r M i x i n or Q u e r y M a n a g e r M i x i n. Previous Next

Copyright 2013, Carl Meyer. Sphinx theme provided by Read the Docs

You might also like