Opened 5 years ago
Closed 5 years ago
#30721 closed Bug (invalid)
Implicit related objects filtration because of the set Manager.
Reported by: | ApaDoctor | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
When abstract model is defined with objects
manager.
And its child-model defines another manager - RelatedManager uses defined manager instead of objects.
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:
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:
>>> 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:
SELECT COUNT(*) AS "__count" FROM "sapp_something" WHERE ("sapp_something"."some_field" = true AND "some_something"."parent_id" = 1)
Change History (1)
comment:1 by , 5 years ago
Component: | Uncategorized → Database layer (models, ORM) |
---|---|
Resolution: | → invalid |
Status: | new → closed |
Version: | 2.2 → master |
Note:
See TracTickets
for help on using tickets.
Thanks for the report, IMO everything works properly, let's analyze this step by step.
You inherited from
SomeAbstractModel
with a manager and define acustom_manager
inSomeThing
.custom_manager
is a default manager forSomeThing
that's why it's used by related manager (e.g.x.children
). In the same timeSomeThing
inheritedobjects
manager fromSomeAbstractModel
(it's no longer a default manager provided by Django, see 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 custom-managers-and-model-inheritance and using-a-custom-reverse-manager).