Opened 4 years ago

Last modified 2 weeks ago

#19222 new Cleanup/optimization

Clarify that custom managers don't apply to intermediate joins

Reported by: andrewbadr Owned by: nobody
Component: Documentation Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by loic)

I have a custom Manager to filter out model instances with where the field deleted is True. I'm using an ORM query that looks like user1.page_set.filter(membership__user=user2).

My expectation is that Membership objects with the deleted flag set are not included in the query. Instead, they are being included.

Change History (6)

comment:1 Changed 4 years ago by mattaustin

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to needsinfo
  • Status changed from new to closed
  • Type changed from Uncategorized to Bug

Attempted to reproduce this, but require more info on model relationships.

comment:2 Changed 2 years ago by jedediah

class BagelManager(Manager):
    use_for_related_fields = True

    def get_query_set(self):
        return super(BagelManager, self).get_query_set().filter(deleted=False)

class Bagel(Model):
    deleted = BooleanField()

    objects = BagelManager()
    all_bagels = Manager()

    def __str__(self):
        return "deleted" if self.deleted else "active"

class Customer(Model):
    bagels = ManyToManyField(Bagel)
>>> Bagel.objects.create(deleted=False)
<Bagel: active>
>>> Bagel.objects.create(deleted=True)
<Bagel: deleted>
>>> Bagel.all_bagels.all()
[<Bagel: active>, <Bagel: deleted>]
>>> Bagel.objects.all()
[<Bagel: active>]
>>> Bagel.objects.filter(deleted=True)

Correct so far... deleted bagel is invisible through default manager

>>> c = Customer.objects.create()
>>> c.bagels.add(*Bagel.all_bagels.all())
>>> c.bagels.all()
[<Bagel: active>]
>>> c.bagels.filter(deleted=True)

Still good... deleted bagel is invisible to related fields

>>> Customer.objects.filter(bagels__deleted=True)
[<Customer: Customer object>]

Here's the problem. The query join sees the deleted bagel. I would expect queries through relations to see the same data as the relations themselves.

This should either be fixed or documented as a known limitation.

comment:3 Changed 2 years ago by jedediah

  • Resolution needsinfo deleted
  • Status changed from closed to new

comment:4 Changed 2 years ago by timo

  • Triage Stage changed from Unreviewed to Accepted
  • Type changed from Bug to Cleanup/optimization

I don't think this a behavior that's going to change, so documentation seems like the way to go. If you'd like to write a patch, I'll be happy to review it.

comment:5 Changed 3 weeks ago by timgraham

  • Keywords use_for_related_fields added

comment:6 Changed 2 weeks ago by loic

  • Description modified (diff)
  • Keywords use_for_related_fields removed
  • Summary changed from Documentation for use_for_related_fields should clarify that it doesn't work for intermediate joins to Clarify that custom managers don't apply to intermediate joins
  • Version changed from 1.4 to master
Note: See TracTickets for help on using tickets.
Back to Top