Opened 11 months ago
Closed 10 months ago
#35073 closed Bug (fixed)
models.SET's callable is called when there are no objects to update.
Reported by: | Fabio Sangiovanni | Owned by: | bcail |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 4.2 |
Severity: | Normal | Keywords: | |
Cc: | Simon Charette, bcail | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Hello everybody.
With an upgrade from Django 4.1 to 4.2 (but also verified in Django 5.0), I've noticed a change in behavior with how on_delete=models.SET is handled.
Given the following models:
from django.db import models class Person(models.Model): name = models.CharField(max_length=32) def __str__(self): return self.name def get_default_person(): return Person.objects.get_or_create(name="ghost")[0] class Pet(models.Model): name = models.CharField(max_length=32) person = models.ForeignKey(Person, related_name="pets", on_delete=models.SET(get_default_person)) def __str__(self): return self.name
I can see what follows in Django 4.2+ (in ./manage.py shell):
>>> from pets.models import Person, Pet >>> Person.objects.all() <QuerySet []> >>> Pet.objects.all() <QuerySet []> >>> Person.objects.create(name="johndoe") <Person: johndoe> >>> Person.objects.all() <QuerySet [<Person: johndoe>]> >>> Person.objects.all().delete() (1, {'pets.Person': 1}) >>> Person.objects.all() <QuerySet [<Person: ghost>]>
What is strange to me is that the "ghost" Person instance is created upon deletion of the "johndoe" instance, even if there are no Pets with a ForeignKey to "johndoe".
Django 4.1 behaves differently (no "ghost" Person is created on deletion of other Person objects).
Is this an intended change? I couldn't find any documentation of this in the release notes.
Thanks so much for your help.
Fabio
Change History (10)
comment:1 by , 11 months ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:2 by , 11 months ago
Cc: | added |
---|---|
Summary: | New behavior of ForeignKey with on_delete=models.SET (Django 4.2 and 5.0) → models.SET's callable is called when there are no objects to update. |
Type: | Uncategorized → Bug |
comment:3 by , 11 months ago
Triage Stage: | Unreviewed → Accepted |
---|
We should fix that.
I think the most straightforward solution is to only set lazy_sub_objs = True
on the function returned by SET
if the value is not a callable. The same problem exists for SET_DEFAULT
when the default is callable.
comment:4 by , 10 months ago
Cc: | added |
---|
@O'ktamjon are you still working on this? If not, I can work on it.
comment:5 by , 10 months ago
I opened an in-progress PR with two unit tests, for SET and SET_DEFAULT.
I pinged Simon on the PR, because I haven't figured out how to fix SET_DEFAULT yet.
comment:7 by , 10 months ago
Patch needs improvement: | set |
---|
comment:9 by , 10 months ago
Owner: | changed from | to
---|---|
Triage Stage: | Accepted → Ready for checkin |
Thanks for the report. Regression in 0701bb8e1f1771b36cdde45602ad377007e372b3.