diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index eee2ecf..5bf75d7 100644
|
a
|
b
|
from django.db.models.related import RelatedObject
|
| 7 | 7 | from django.db.models.query import QuerySet |
| 8 | 8 | from django.db.models.query_utils import QueryWrapper |
| 9 | 9 | from django.db.models.deletion import CASCADE |
| | 10 | from django.db.models.manager import ManagerDescriptor |
| 10 | 11 | from django.utils.encoding import smart_unicode |
| 11 | 12 | from django.utils.translation import ugettext_lazy as _, string_concat |
| 12 | 13 | from django.utils.functional import curry |
| … |
… |
class ForeignRelatedObjectsDescriptor(object):
|
| 386 | 387 | if instance is None: |
| 387 | 388 | return self |
| 388 | 389 | |
| 389 | | return self.create_manager(instance, |
| | 390 | def _other_fk_managers(manager): |
| | 391 | """ |
| | 392 | Selects a manager from the list of the model's managers, useful |
| | 393 | in the case of choosing a manager which is not the default, in a reverse relation. |
| | 394 | """ |
| | 395 | if manager in self.related.model.__dict__ and isinstance(self.related.model.__dict__.get(manager, None), ManagerDescriptor): |
| | 396 | return self.create_manager(instance, self.related.model.__dict__.get(manager).manager.__class__) |
| | 397 | else: |
| | 398 | raise AttributeError("Manager %s does not exist" % manager) |
| | 399 | |
| | 400 | manager = self.create_manager(instance, |
| 390 | 401 | self.related.model._default_manager.__class__) |
| | 402 | manager.managers = _other_fk_managers |
| | 403 | return manager |
| 391 | 404 | |
| 392 | 405 | def __set__(self, instance, value): |
| 393 | 406 | if instance is None: |
| … |
… |
class ManyRelatedObjectsDescriptor(object):
|
| 671 | 684 | # model's default manager. |
| 672 | 685 | rel_model = self.related.model |
| 673 | 686 | superclass = rel_model._default_manager.__class__ |
| | 687 | |
| 674 | 688 | RelatedManager = create_many_related_manager(superclass, self.related.field.rel) |
| 675 | 689 | |
| 676 | 690 | manager = RelatedManager( |
| … |
… |
class ManyRelatedObjectsDescriptor(object):
|
| 684 | 698 | through=self.related.field.rel.through, |
| 685 | 699 | ) |
| 686 | 700 | |
| | 701 | def _other_m2m_managers(manager): |
| | 702 | """ |
| | 703 | Selects a manager from the list of the model's managers, useful |
| | 704 | in the case of choosing a manager which is not the default, in a reverse relation. |
| | 705 | """ |
| | 706 | if manager in self.related.model.__dict__ and isinstance(self.related.model.__dict__.get(manager, None), ManagerDescriptor): |
| | 707 | return self.create_many_related_manager(self.related.model.__dict__.get(manager).manager.__class__, self.related.field.rel) |
| | 708 | else: |
| | 709 | raise AttributeError("Manager %s does not exist" % manager) |
| | 710 | |
| | 711 | manager.managers = _other_m2m_managers |
| 687 | 712 | return manager |
| 688 | 713 | |
| 689 | 714 | def __set__(self, instance, value): |
diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt
index 23ed124..26e502f 100644
|
a
|
b
|
Each "reverse" operation described in this section has an immediate effect on
|
| 1036 | 1036 | the database. Every addition, creation and deletion is immediately and |
| 1037 | 1037 | automatically saved to the database. |
| 1038 | 1038 | |
| | 1039 | The ``entry_set`` notation, returns the default ``Manager`` defined for the |
| | 1040 | ``Entry`` model, if you want to choose a custom manager, use the ``managers()`` |
| | 1041 | method of ``entry_set``. For example:: |
| | 1042 | |
| | 1043 | b = Blog.objects.get(id=1) |
| | 1044 | # Selects the custom_manager attribute, defined on Entry |
| | 1045 | b.entry_set.managers('custom_manager') |
| | 1046 | |
| 1039 | 1047 | .. _m2m-reverse-relationships: |
| 1040 | 1048 | |
| 1041 | 1049 | Many-to-many relationships |
| … |
… |
An example makes this easier to understand::
|
| 1062 | 1070 | Like ``ForeignKey``, ``ManyToManyField`` can specify ``related_name``. In the |
| 1063 | 1071 | above example, if the ``ManyToManyField`` in ``Entry`` had specified |
| 1064 | 1072 | ``related_name='entries'``, then each ``Author`` instance would have an |
| 1065 | | ``entries`` attribute instead of ``entry_set``. |
| | 1073 | ``entries`` attribute instead of ``entry_set``. The ``entries`` attribute, |
| | 1074 | also has a ``managers()`` method to select custom managers. For example:: |
| | 1075 | |
| | 1076 | b = Author.objects.get(id=5) |
| | 1077 | # Selects the custom_manager attribute, defined on Entry |
| | 1078 | b.entries.managers('custom_manager') |
| | 1079 | |
| 1066 | 1080 | |
| 1067 | 1081 | One-to-one relationships |
| 1068 | 1082 | ------------------------ |
diff --git a/tests/modeltests/custom_managers/models.py b/tests/modeltests/custom_managers/models.py
index 1052552..89a665c 100644
|
a
|
b
|
class FastCarManager(models.Manager):
|
| 50 | 50 | |
| 51 | 51 | class Car(models.Model): |
| 52 | 52 | name = models.CharField(max_length=10) |
| | 53 | manufacturer = models.ForeignKey('Manufacturer') |
| 53 | 54 | mileage = models.IntegerField() |
| 54 | 55 | top_speed = models.IntegerField(help_text="In miles per hour.") |
| 55 | 56 | cars = models.Manager() |
| … |
… |
class Car(models.Model):
|
| 57 | 58 | |
| 58 | 59 | def __unicode__(self): |
| 59 | 60 | return self.name |
| | 61 | |
| | 62 | class Manufacturer(models.Model): |
| | 63 | name = models.CharField(max_length=10) |
| | 64 | country = models.CharField(max_length=20) |
diff --git a/tests/modeltests/custom_managers/tests.py b/tests/modeltests/custom_managers/tests.py
index 8721e9a..1ad41e8 100644
|
a
|
b
|
|
| 1 | 1 | from django.test import TestCase |
| 2 | 2 | |
| 3 | | from models import Person, Book, Car, PersonManager, PublishedBookManager |
| | 3 | from models import Person, Book, Car, Manufacturer, PersonManager, PublishedBookManager |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | class CustomManagerTests(TestCase): |
| … |
… |
class CustomManagerTests(TestCase):
|
| 40 | 40 | lambda b: b.title |
| 41 | 41 | ) |
| 42 | 42 | |
| 43 | | c1 = Car.cars.create(name="Corvette", mileage=21, top_speed=180) |
| 44 | | c2 = Car.cars.create(name="Neon", mileage=31, top_speed=100) |
| | 43 | chevy = Manufacturer.objects.create(name="Chevrolet", country="USA") |
| | 44 | dodge = Manufacturer.objects.create(name="Dodge", country="USA") |
| | 45 | |
| | 46 | c1 = Car.cars.create(name="Corvette", mileage=21, top_speed=180, manufacturer=chevy) |
| | 47 | c2 = Car.cars.create(name="Neon", mileage=31, top_speed=100, manufacturer=dodge) |
| | 48 | c3 = Car.cars.create(name="Viper", mileage=14, top_speed=200, manufacturer=dodge) |
| 45 | 49 | |
| 46 | 50 | self.assertQuerysetEqual( |
| 47 | 51 | Car.cars.order_by("name"), [ |
| 48 | 52 | "Corvette", |
| 49 | 53 | "Neon", |
| | 54 | "Viper" |
| 50 | 55 | ], |
| 51 | 56 | lambda c: c.name |
| 52 | 57 | ) |
| … |
… |
class CustomManagerTests(TestCase):
|
| 54 | 59 | self.assertQuerysetEqual( |
| 55 | 60 | Car.fast_cars.all(), [ |
| 56 | 61 | "Corvette", |
| | 62 | "Viper", |
| 57 | 63 | ], |
| 58 | 64 | lambda c: c.name |
| 59 | 65 | ) |
| … |
… |
class CustomManagerTests(TestCase):
|
| 66 | 72 | Car._default_manager.order_by("name"), [ |
| 67 | 73 | "Corvette", |
| 68 | 74 | "Neon", |
| | 75 | "Viper", |
| | 76 | ], |
| | 77 | lambda c: c.name |
| | 78 | ) |
| | 79 | |
| | 80 | #Choosing a custom manager in a reverse relation |
| | 81 | self.assertQuerysetEqual( |
| | 82 | dodge.car_set.managers('fast_cars').all(), [ |
| | 83 | "Viper", |
| 69 | 84 | ], |
| 70 | 85 | lambda c: c.name |
| 71 | 86 | ) |