[Django] #30721: Implicit related objects filtration because of the set Manager.

24 views
Skip to first unread message

Django

unread,
Aug 21, 2019, 11:42:26 AM8/21/19
to django-...@googlegroups.com
#30721: Implicit related objects filtration because of the set Manager.
-----------------------------------------+------------------------
Reporter: ApaDoctor | Owner: nobody
Type: Bug | Status: new
Component: Uncategorized | Version: 2.2
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
When abstract model is defined with `objects` manager.
And its child-model defines another manager - RelatedManager uses defined
manager instead of objects.

{{{#!python
class SomeAbstractModel(models.Model):
class Meta:
abstract = True

objects = models.Manager()


class CustomManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(some_field=True)


class SomeThing(SomeAbstractModel):
some_field = models.BooleanField()

parent = models.ForeignKey(
"SomeThing", related_name="children", on_delete=models.SET_NULL,
null=True
)

custom_objects = CustomManager()
}}}

So we have abstract model, which defines `objects` manager for the model.

Our model uses that abstract class.

I created some objects:
{{{#!python
SomeThing(some_field=True).save()
SomeThing.objects.bulk_create([SomeThing(some_field=bool(x%2),
parent_id=1) for x in range(0,6)])
}}}

After i reloaded shell i tried to make queries:
{{{#!python
>>> x = SomeThing.objects.get(id=1)
>>> x.children.count()
3
>>>SomeThing.objects.filter(parent_id=1).count()
6
}}}

Generated raw SQL for first query is:

{{{#!sql
SELECT COUNT(*) AS "__count" FROM "sapp_something" WHERE
("sapp_something"."some_field" = true AND "some_something"."parent_id" =
1)
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30721>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Aug 21, 2019, 2:49:24 PM8/21/19
to django-...@googlegroups.com
#30721: Implicit related objects filtration because of the set Manager.
-------------------------------------+-------------------------------------
Reporter: ApaDoctor | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution: invalid

Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by felixxm):

* status: new => closed
* component: Uncategorized => Database layer (models, ORM)
* version: 2.2 => master
* resolution: => invalid


Comment:

Thanks for the report, IMO everything works properly, let's analyze this
step by step.

You inherited from `SomeAbstractModel` with a manager and define a
`custom_manager` in `SomeThing`. `custom_manager` is a default manager for
`SomeThing` that's why it's used by related manager (e.g. `x.children`).
In the same time `SomeThing` inherited `objects` manager from
`SomeAbstractModel` (it's no longer a default manager provided by Django,
see [https://docs.djangoproject.com/en/2.2/topics/db/managers/#manager-
names manager-names]) so when you call it explicit e.g.
`SomeThing.objects.filter(parent_id=1).count()` it returns all rows,
without an extra filter (see also
[https://docs.djangoproject.com/en/2.2/topics/db/managers/#custom-
managers-and-model-inheritance custom-managers-and-model-inheritance] and
[https://docs.djangoproject.com/en/2.2/topics/db/queries/#using-a-custom-
reverse-manager using-a-custom-reverse-manager]).

--
Ticket URL: <https://code.djangoproject.com/ticket/30721#comment:1>

Reply all
Reply to author
Forward
0 new messages