mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	git-svn-id: http://code.djangoproject.com/svn/django/trunk@8506 bcc190cf-cafb-0310-a4f2-bffc1f526a37
		
			
				
	
	
		
			192 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| .. _topics-db-managers:
 | |
| 
 | |
| ========
 | |
| Managers
 | |
| ========
 | |
| 
 | |
| .. currentmodule:: django.db.models
 | |
| 
 | |
| .. class:: Manager()
 | |
| 
 | |
| A ``Manager`` is the interface through which database query operations are
 | |
| provided to Django models. At least one ``Manager`` exists for every model in
 | |
| a Django application.
 | |
| 
 | |
| The way ``Manager`` classes work is documented :ref:`topics-db-queries`; this
 | |
| document specifically touches on model options that customize ``Manager``
 | |
| behavior.
 | |
| 
 | |
| Manager names
 | |
| =============
 | |
| 
 | |
| By default, Django adds a ``Manager`` with the name ``objects`` to every Django
 | |
| model class. However, if you want to use ``objects`` as a field name, or if you
 | |
| want to use a name other than ``objects`` for the ``Manager``, you can rename
 | |
| it on a per-model basis. To rename the ``Manager`` for a given class, define a
 | |
| class attribute of type ``models.Manager()`` on that model. For example::
 | |
| 
 | |
|     from django.db import models
 | |
| 
 | |
|     class Person(models.Model):
 | |
|         #...
 | |
|         people = models.Manager()
 | |
| 
 | |
| Using this example model, ``Person.objects`` will generate an
 | |
| ``AttributeError`` exception, but ``Person.people.all()`` will provide a list
 | |
| of all ``Person`` objects.
 | |
| 
 | |
| .. _custom-managers:
 | |
| 
 | |
| Custom Managers
 | |
| ===============
 | |
| 
 | |
| You can use a custom ``Manager`` in a particular model by extending the base
 | |
| ``Manager`` class and instantiating your custom ``Manager`` in your model.
 | |
| 
 | |
| There are two reasons you might want to customize a ``Manager``: to add extra
 | |
| ``Manager`` methods, and/or to modify the initial ``QuerySet`` the ``Manager``
 | |
| returns.
 | |
| 
 | |
| Adding extra Manager methods
 | |
| ----------------------------
 | |
| 
 | |
| Adding extra ``Manager`` methods is the preferred way to add "table-level"
 | |
| functionality to your models. (For "row-level" functionality -- i.e., functions
 | |
| that act on a single instance of a model object -- use :ref:`Model methods
 | |
| <model-methods>`, not custom ``Manager`` methods.)
 | |
| 
 | |
| A custom ``Manager`` method can return anything you want. It doesn't have to
 | |
| return a ``QuerySet``.
 | |
| 
 | |
| For example, this custom ``Manager`` offers a method ``with_counts()``, which
 | |
| returns a list of all ``OpinionPoll`` objects, each with an extra
 | |
| ``num_responses`` attribute that is the result of an aggregate query::
 | |
| 
 | |
|     class PollManager(models.Manager):
 | |
|         def with_counts(self):
 | |
|             from django.db import connection
 | |
|             cursor = connection.cursor()
 | |
|             cursor.execute("""
 | |
|                 SELECT p.id, p.question, p.poll_date, COUNT(*)
 | |
|                 FROM polls_opinionpoll p, polls_response r
 | |
|                 WHERE p.id = r.poll_id
 | |
|                 GROUP BY 1, 2, 3
 | |
|                 ORDER BY 3 DESC""")
 | |
|             result_list = []
 | |
|             for row in cursor.fetchall():
 | |
|                 p = self.model(id=row[0], question=row[1], poll_date=row[2])
 | |
|                 p.num_responses = row[3]
 | |
|                 result_list.append(p)
 | |
|             return result_list
 | |
| 
 | |
|     class OpinionPoll(models.Model):
 | |
|         question = models.CharField(max_length=200)
 | |
|         poll_date = models.DateField()
 | |
|         objects = PollManager()
 | |
| 
 | |
|     class Response(models.Model):
 | |
|         poll = models.ForeignKey(Poll)
 | |
|         person_name = models.CharField(max_length=50)
 | |
|         response = models.TextField()
 | |
| 
 | |
| With this example, you'd use ``OpinionPoll.objects.with_counts()`` to return
 | |
| that list of ``OpinionPoll`` objects with ``num_responses`` attributes.
 | |
| 
 | |
| Another thing to note about this example is that ``Manager`` methods can
 | |
| access ``self.model`` to get the model class to which they're attached.
 | |
| 
 | |
| Modifying initial Manager QuerySets
 | |
| -----------------------------------
 | |
| 
 | |
| A ``Manager``'s base ``QuerySet`` returns all objects in the system. For
 | |
| example, using this model::
 | |
| 
 | |
|     class Book(models.Model):
 | |
|         title = models.CharField(max_length=100)
 | |
|         author = models.CharField(max_length=50)
 | |
| 
 | |
| ...the statement ``Book.objects.all()`` will return all books in the database.
 | |
| 
 | |
| You can override a ``Manager``\'s base ``QuerySet`` by overriding the
 | |
| ``Manager.get_query_set()`` method. ``get_query_set()`` should return a
 | |
| ``QuerySet`` with the properties you require.
 | |
| 
 | |
| For example, the following model has *two* ``Manager``\s -- one that returns
 | |
| all objects, and one that returns only the books by Roald Dahl::
 | |
| 
 | |
|     # First, define the Manager subclass.
 | |
|     class DahlBookManager(models.Manager):
 | |
|         def get_query_set(self):
 | |
|             return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl')
 | |
| 
 | |
|     # Then hook it into the Book model explicitly.
 | |
|     class Book(models.Model):
 | |
|         title = models.CharField(max_length=100)
 | |
|         author = models.CharField(max_length=50)
 | |
| 
 | |
|         objects = models.Manager() # The default manager.
 | |
|         dahl_objects = DahlBookManager() # The Dahl-specific manager.
 | |
| 
 | |
| With this sample model, ``Book.objects.all()`` will return all books in the
 | |
| database, but ``Book.dahl_objects.all()`` will only return the ones written by
 | |
| Roald Dahl.
 | |
| 
 | |
| Of course, because ``get_query_set()`` returns a ``QuerySet`` object, you can
 | |
| use ``filter()``, ``exclude()`` and all the other ``QuerySet`` methods on it.
 | |
| So these statements are all legal::
 | |
| 
 | |
|     Book.dahl_objects.all()
 | |
|     Book.dahl_objects.filter(title='Matilda')
 | |
|     Book.dahl_objects.count()
 | |
| 
 | |
| This example also pointed out another interesting technique: using multiple
 | |
| managers on the same model. You can attach as many ``Manager()`` instances to
 | |
| a model as you'd like. This is an easy way to define common "filters" for your
 | |
| models.
 | |
| 
 | |
| For example::
 | |
| 
 | |
|     class MaleManager(models.Manager):
 | |
|         def get_query_set(self):
 | |
|             return super(MaleManager, self).get_query_set().filter(sex='M')
 | |
| 
 | |
|     class FemaleManager(models.Manager):
 | |
|         def get_query_set(self):
 | |
|             return super(FemaleManager, self).get_query_set().filter(sex='F')
 | |
| 
 | |
|     class Person(models.Model):
 | |
|         first_name = models.CharField(max_length=50)
 | |
|         last_name = models.CharField(max_length=50)
 | |
|         sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))
 | |
|         people = models.Manager()
 | |
|         men = MaleManager()
 | |
|         women = FemaleManager()
 | |
| 
 | |
| This example allows you to request ``Person.men.all()``, ``Person.women.all()``,
 | |
| and ``Person.people.all()``, yielding predictable results.
 | |
| 
 | |
| If you use custom ``Manager`` objects, take note that the first
 | |
| ``Manager`` Django encounters (in the order in which they're defined
 | |
| in the model) has a special status. Django interprets this first
 | |
| ``Manager`` defined in a class as the "default" ``Manager``, and
 | |
| several parts of Django (though not the admin application) will use
 | |
| that ``Manager`` exclusively for that model. As a result, it's often a
 | |
| good idea to be careful in your choice of default manager, in order to
 | |
| avoid a situation where overriding of ``get_query_set()`` results in
 | |
| an inability to retrieve objects you'd like to work with.
 | |
| 
 | |
| Using managers for related object access
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| By default, Django uses a "bare" (i.e. default) manager when accessing related
 | |
| objects (i.e. ``choice.poll``). If this default isn't appropriate for your
 | |
| default manager, you can force Django to use a custom manager for related object
 | |
| attributes by giving it a ``use_for_related_fields`` property::
 | |
| 
 | |
|     class MyManager(models.Manager)::
 | |
|         use_for_related_fields = True
 | |
|         ...
 | |
|         
 | |
| 
 | |
|         ...
 |