Opened 43 hours ago
Last modified 14 hours ago
#36235 assigned Bug
RelatedManager.all().get_or_create() does not work
Reported by: | Nick Pope | Owned by: | JaeHyuckSa |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | get_or_create, related, manager |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
When accessing the queryset for a related manager, .get_or_create()
and .update_or_create()
lose context of the related instance.
Calling on the related manager works as expected:
publisher.books.get_or_create(name="The Very Hungry Caterpillar")
This is the case that was fixed by #3121 and #23611.
But calling on the queryset causes an IntegrityError
to be raised:
publisher.books.all().get_or_create(name="The Very Hungry Caterpillar")
This can be a subtle failure that is hard to understand, especially if publisher.books.all()
is assigned to a variable earlier.
The challenge here is that the overridden methods on the manager set kwargs[self.field.name] = self.instance
.
We'd need to be able to pass this information down to the queryset. It looks like this might already be available in _known_related_objects
which is set by RelatedManager._apply_rel_filters()
, so that would be a good starting point for investigation.
We would also need to check whether something needs to be done to select the correct database as RelatedManager.get_or_create()
has handling for this:
db = router.db_for_write(self.model, instance=self.instance)
If this is something we can't fix reliably, then we should update the admonition under .get_or_create() in the docs and probably update .update_or_create() to make this and other issues related to use through RelatedManager
more clear.
Change History (6)
comment:1 by , 43 hours ago
comment:2 by , 43 hours ago
Description: | modified (diff) |
---|
comment:4 by , 19 hours ago
Has patch: | set |
---|---|
Owner: | set to |
Status: | new → assigned |
comment:5 by , 19 hours ago
Has patch: | unset |
---|
comment:6 by , 14 hours ago
Has patch: | set |
---|
The following test can be added to
GetOrCreateTests
intests/get_or_create/tests.py
belowtest_get_or_create_on_related_manager
: