Opened 4 months ago
Last modified 5 days ago
#36888 assigned Bug
acreate method doesn't call asave
| Reported by: | Mateusz Szymanowski | Owned by: | Mateusz Szymanowski |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 6.0 |
| Severity: | Normal | Keywords: | acreate asave async |
| Cc: | Mateusz Szymanowski | Triage Stage: | Someday/Maybe |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | yes |
| Easy pickings: | no | UI/UX: | no |
Description
acreate doesn't call asave method.
When you use async Django methods and you want to add custom logic in asave method, when you create your object with acreate, it doesn't call your asave method.
class SimpleModel(models.Model):
field = models.IntegerField()
async def asave(self, *args, **kwargs):
self.field += 1
await super().asave(*args, **kwargs)
obj = await SimpleModel.objects.acreate(field=4)
obj.field # returns 4, should be 5
When you run create, it calls save().
Change History (11)
comment:1 by , 4 months ago
| Has patch: | set |
|---|
comment:2 by , 4 months ago
| Easy pickings: | unset |
|---|---|
| Keywords: | async added |
| Triage Stage: | Unreviewed → Accepted |
comment:3 by , 4 months ago
| Patch needs improvement: | set |
|---|
comment:4 by , 4 months ago
| Owner: | changed from to |
|---|
comment:5 by , 3 months ago
| Owner: | changed from to |
|---|
comment:6 by , 3 months ago
| Needs tests: | set |
|---|---|
| Patch needs improvement: | unset |
comment:8 by , 3 months ago
| Needs tests: | unset |
|---|---|
| Owner: | changed from to |
Restoring the previous owner since the PR is needing a re-review, but owner did not update the ticket flags I think.
comment:9 by , 3 months ago
Hello Natalia, my bad; I thought this ticket was inactive. I lately realized the owner's PR is still ongoing, and there was no activity here in the track ticket.
comment:10 by , 3 months ago
| Patch needs improvement: | set |
|---|
comment:11 by , 5 days ago
| Triage Stage: | Accepted → Someday/Maybe |
|---|
Before, acreate() had a sync_to_async() right off the bat:
async def acreate(self, **kwargs): return await sync_to_async(self.create)(**kwargs)
Attempts in the PRs to remove that sync_to_async() stalled on the fact that GenericForeignKeyDescriptor.__set__ accesses the database (see generic_relations.tests.GenericRelationsTests.test_aadd).
If we're just shuffling around *where* the sync_to_async lies, then we're not accomplishing very much, as pointed out in the reviews. I posted a sketch of an async interface for Model instantiation.
I think we need both that as well as an async implementation of ContentType methods (aget_content_type() etc.) before we can advance this.
If someone can confirm the general direction, we can open separate tickets for those.
Thank you Mateusz for your report! Great catch.