managers vs static/class methods ?

1,069 views
Skip to first unread message

glopglop

unread,
Feb 20, 2008, 8:26:55 AM2/20/08
to Django users
Hi, I've yet t understand the difference and benefit of user a custom
manager method for a model over defining a static/classmethod
returning a queryset ?

Why add a new concept and what does it add here ? Just curious that
I'm currently missing something using staticmethod for my models such
as :

class Foo(models.Model) :
bar=models.IntegerField('a number')

@staticmethod
def positives() : return Foo.filter(bar__gt=0)

Steven Armstrong

unread,
Feb 20, 2008, 8:57:54 AM2/20/08
to django...@googlegroups.com
glopglop wrote on 02/20/08 14:26:

Through a custom manager you can change the behavior of django as a whole.

If you do:

class Foo(models.Model) :
bar = models.IntegerField('a number')
objects = MyFancyManager()

it is also used e.g. by the django admin

Your static method only works with your own code.

BTW: Your static method should probably use Foo.objects.filter(bar_gt=0)

glopglop

unread,
Feb 20, 2008, 9:42:54 AM2/20/08
to Django users


Thx for your reply.

> Through a custom manager you can change the behavior of django as a whole.
>
> If you do:
>
> class Foo(models.Model) :
> bar = models.IntegerField('a number')
> objects = MyFancyManager()
>
> it is also used e.g. by the django admin
> Your static method only works with your own code.


OK, but does that mean that it mainly is useful when you replace the
default "objects" manager ?

I understand you could also reuse it from model to model, but in my
code I have rarely found reusing those methods between different
models, except some ways that would generally be better solved with
model inheritance.


> BTW: Your static method should probably use Foo.objects.filter(bar_gt=0)
Sure, my fault.

Steven Armstrong

unread,
Feb 20, 2008, 10:00:17 AM2/20/08
to django...@googlegroups.com
glopglop wrote on 02/20/08 15:42:

>
>
> Thx for your reply.
>
>> Through a custom manager you can change the behavior of django as a whole.
>>
>> If you do:
>>
>> class Foo(models.Model) :
>> bar = models.IntegerField('a number')
>> objects = MyFancyManager()
>>
>> it is also used e.g. by the django admin
>> Your static method only works with your own code.
>
>
> OK, but does that mean that it mainly is useful when you replace the
> default "objects" manager ?

AFAICT its only a matter of personal preference. Use which ever method
you like best.

Michael Elsdörfer

unread,
Feb 20, 2008, 11:07:49 AM2/20/08
to django...@googlegroups.com
> I understand you could also reuse it from model to model, but in my
> code I have rarely found reusing those methods between different
> models, except some ways that would generally be better solved with
> model inheritance.

Managers as a concept are very useful. For example, they can also
inherit from one another, which I use in a couple instances. A base
class might provide the initial queryset, which is further modified by
descendant managers: One returning only rows that are intended for the
general public, while another might allow access to everything,
including e.g. unapproved records.

With static methods, you also couldn't do things like:

if request.user.is_admin:
manager = MyModel.objects
else:
manager = MyModel.public_objects

# work with ``manager``

Michael

Jacob Kaplan-Moss

unread,
Feb 20, 2008, 12:08:04 PM2/20/08
to django...@googlegroups.com
On 2/20/08, Steven Armstrong <s...@c-area.ch> wrote:
> AFAICT its only a matter of personal preference. Use which ever method
> you like best.

Well, there is a distinct philosophy behind the manager concept; we
didn't just pull the idea out of thin air :)

The basic idea is that manager act as the bridge between Python
classes and relational database tables. Managers, then, represent
database-table-wide operations -- not, say, row-level operations
(which are methods on model instances) or Python-level operations
(which don't know anything about a database at all).

For a concrete example, consider the difference in behavior between
``Model.__init__`` and ``Model.objects.create``. Both "create
something", but both do *very* different things.

``Model.__init__`` creates a new model instance, but doesn't touch the
database in any way -- it's just like any other Python constructor
that returns an instance. ``Model.objects.create()`` also returns a
new model instance, but *also* creates a new row in the database
table. Confuses those two method at your peril!

So the distinguishing factor between classmethods and manager methods
should be the database. In the original example here, ``positives()``
should be a manager method to keep in line with this philosophy.
That's not to say that there's anything "wrong" with making it
classmethod, but if you're trying to be as "django-esque" as possible,
you'd make that method a manager method.

Jacob

glopglop

unread,
Feb 21, 2008, 10:26:53 AM2/21/08
to Django users
Fine, it's clearer for me now (with the added smart examples).

"The distinguishing factor between manager methods and class or static
methods
should be the database. Managers handle table-wide operations ; Python-
level operations
don't know anything about a database at all."

Maybe a sentence like that should be added in the documentation (as a
note or something) explaining managers, to make that thing more
explicit (because it's an important concept to be shared and I'm sure
I am not the only one to wonder if it's worth it).

glopglop

unread,
Feb 21, 2008, 10:35:56 AM2/21/08
to Django users


On 20 fév, 17:07, Michael Elsdörfer <mich...@elsdoerfer.info> wrote:
> > I understand you could also reuse it from model to model, but in my
> > code I have rarely found reusing those methods between different
> > models, except some ways that would generally be better solved with
> > model inheritance.
>
> Managers as a concept are very useful. For example, they can also
> inherit from one another, which I use in a couple instances. A base
> class might provide the initial queryset, which is further modified by
> descendant managers: One returning only rows that are intended for the
> general public, while another might allow access to everything,
> including e.g. unapproved records.
Couldn't that be done using chaining staticmethods, such as

@classmethod
def even_positive_low(cls) : return cls.positive().filter(bar__lt=25)

>
> With static methods, you also couldn't do things like:
>
> if request.user.is_admin:
> manager = MyModel.objects
> else:
> manager = MyModel.public_objects
>
> # work with ``manager``
Not trying to be slow-witted, but couldn't you do

objects = MyModel.unfiltered() if request.user.is_admin else
MyModel.filtered()
(where objects is a queryset)

is there a functionnal difference or is it more of a style (which can
have its importance) ?

James Bennett

unread,
Feb 21, 2008, 11:13:43 AM2/21/08
to django...@googlegroups.com
On Thu, Feb 21, 2008 at 9:35 AM, glopglop <xavier...@gmail.com> wrote:
> Not trying to be slow-witted, but couldn't you do
>
> objects = MyModel.unfiltered() if request.user.is_admin else
> MyModel.filtered()
> (where objects is a queryset)
>
> is there a functionnal difference or is it more of a style (which can
> have its importance) ?

This only works in Python 2.5. The other works in every version of
Python Django supports.


--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."

Reply all
Reply to author
Forward
0 new messages