Ticket #3871: 3871-patch.diff

File 3871-patch.diff, 5.6 KB (added by v1v3kn, 4 years ago)

Patch that fixes this by letting the user choose the manager by a .managers() function.

  • django/db/models/fields/related.py

    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 
    77from django.db.models.query import QuerySet
    88from django.db.models.query_utils import QueryWrapper
    99from django.db.models.deletion import CASCADE
     10from django.db.models.manager import ManagerDescriptor
    1011from django.utils.encoding import smart_unicode
    1112from django.utils.translation import ugettext_lazy as _, string_concat
    1213from django.utils.functional import curry
    class ForeignRelatedObjectsDescriptor(object): 
    386387        if instance is None:
    387388            return self
    388389
    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,
    390401                self.related.model._default_manager.__class__)
     402        manager.managers = _other_fk_managers
     403        return manager
    391404
    392405    def __set__(self, instance, value):
    393406        if instance is None:
    class ManyRelatedObjectsDescriptor(object): 
    671684        # model's default manager.
    672685        rel_model = self.related.model
    673686        superclass = rel_model._default_manager.__class__
     687
    674688        RelatedManager = create_many_related_manager(superclass, self.related.field.rel)
    675689
    676690        manager = RelatedManager(
    class ManyRelatedObjectsDescriptor(object): 
    684698            through=self.related.field.rel.through,
    685699        )
    686700
     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
    687712        return manager
    688713
    689714    def __set__(self, instance, value):
  • tests/modeltests/custom_managers/models.py

    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): 
    5050
    5151class Car(models.Model):
    5252    name = models.CharField(max_length=10)
     53    manufacturer = models.ForeignKey('Manufacturer')
    5354    mileage = models.IntegerField()
    5455    top_speed = models.IntegerField(help_text="In miles per hour.")
    5556    cars = models.Manager()
    class Car(models.Model): 
    5758
    5859    def __unicode__(self):
    5960        return self.name
     61
     62class Manufacturer(models.Model):
     63    name = models.CharField(max_length=10)
     64    country = models.CharField(max_length=20)
  • tests/modeltests/custom_managers/tests.py

    diff --git a/tests/modeltests/custom_managers/tests.py b/tests/modeltests/custom_managers/tests.py
    index 8721e9a..1ad41e8 100644
    a b  
    11from django.test import TestCase
    22
    3 from models import Person, Book, Car, PersonManager, PublishedBookManager
     3from models import Person, Book, Car, Manufacturer, PersonManager, PublishedBookManager
    44
    55
    66class CustomManagerTests(TestCase):
    class CustomManagerTests(TestCase): 
    4040            lambda b: b.title
    4141        )
    4242
    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)
    4549
    4650        self.assertQuerysetEqual(
    4751            Car.cars.order_by("name"), [
    4852                "Corvette",
    4953                "Neon",
     54                "Viper"
    5055            ],
    5156            lambda c: c.name
    5257        )
    class CustomManagerTests(TestCase): 
    5459        self.assertQuerysetEqual(
    5560            Car.fast_cars.all(), [
    5661                "Corvette",
     62                "Viper",
    5763            ],
    5864            lambda c: c.name
    5965        )
    class CustomManagerTests(TestCase): 
    6672            Car._default_manager.order_by("name"), [
    6773                "Corvette",
    6874                "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",
    6984            ],
    7085            lambda c: c.name
    7186        )
Back to Top