mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #35019 -- Fixed save() on models with both GeneratedFields and ForeignKeys.
Thanks Deb Kumar Das for the report.
Regression in f333e3513e
.
This commit is contained in:
parent
eeb2119985
commit
b287af5dc9
@ -781,7 +781,11 @@ class Model(AltersData, metaclass=ModelBase):
|
||||
if force_insert and (force_update or update_fields):
|
||||
raise ValueError("Cannot force both insert and updating in model saving.")
|
||||
|
||||
deferred_fields = self.get_deferred_fields()
|
||||
deferred_non_generated_fields = {
|
||||
f.attname
|
||||
for f in self._meta.concrete_fields
|
||||
if f.attname not in self.__dict__ and f.generated is False
|
||||
}
|
||||
if update_fields is not None:
|
||||
# If update_fields is empty, skip the save. We do also check for
|
||||
# no-op saves later on for inheritance cases. This bailout is
|
||||
@ -802,12 +806,16 @@ class Model(AltersData, metaclass=ModelBase):
|
||||
|
||||
# If saving to the same database, and this model is deferred, then
|
||||
# automatically do an "update_fields" save on the loaded fields.
|
||||
elif not force_insert and deferred_fields and using == self._state.db:
|
||||
elif (
|
||||
not force_insert
|
||||
and deferred_non_generated_fields
|
||||
and using == self._state.db
|
||||
):
|
||||
field_names = set()
|
||||
for field in self._meta.concrete_fields:
|
||||
if not field.primary_key and not hasattr(field, "through"):
|
||||
field_names.add(field.attname)
|
||||
loaded_fields = field_names.difference(deferred_fields)
|
||||
loaded_fields = field_names.difference(deferred_non_generated_fields)
|
||||
if loaded_fields:
|
||||
update_fields = frozenset(loaded_fields)
|
||||
|
||||
|
@ -16,3 +16,7 @@ Bugfixes
|
||||
* Fixed a long standing bug in handling the ``RETURNING INTO`` clause that
|
||||
caused a crash when creating a model instance with a ``GeneratedField`` which
|
||||
``output_field`` had backend-specific converters (:ticket:`35024`).
|
||||
|
||||
* Fixed a regression in Django 5.0 that caused a crash of ``Model.save()`` for
|
||||
models with both ``GeneratedField`` and ``ForeignKey`` fields
|
||||
(:ticket:`35019`).
|
||||
|
@ -502,6 +502,7 @@ class GeneratedModel(models.Model):
|
||||
output_field=models.IntegerField(),
|
||||
db_persist=True,
|
||||
)
|
||||
fk = models.ForeignKey(Foo, on_delete=models.CASCADE, null=True)
|
||||
|
||||
class Meta:
|
||||
required_db_features = {"supports_stored_generated_columns"}
|
||||
@ -515,6 +516,7 @@ class GeneratedModelVirtual(models.Model):
|
||||
output_field=models.IntegerField(),
|
||||
db_persist=False,
|
||||
)
|
||||
fk = models.ForeignKey(Foo, on_delete=models.CASCADE, null=True)
|
||||
|
||||
class Meta:
|
||||
required_db_features = {"supports_virtual_generated_columns"}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import uuid
|
||||
from decimal import Decimal
|
||||
|
||||
from django.apps import apps
|
||||
from django.db import IntegrityError, connection
|
||||
@ -15,6 +16,7 @@ from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature
|
||||
from django.test.utils import isolate_apps
|
||||
|
||||
from .models import (
|
||||
Foo,
|
||||
GeneratedModel,
|
||||
GeneratedModelFieldWithConverters,
|
||||
GeneratedModelNull,
|
||||
@ -187,6 +189,19 @@ class GeneratedFieldTestMixin:
|
||||
m.refresh_from_db()
|
||||
self.assertEqual(m.field, 8)
|
||||
|
||||
def test_save_model_with_foreign_key(self):
|
||||
fk_object = Foo.objects.create(a="abc", d=Decimal("12.34"))
|
||||
m = self.base_model(a=1, b=2, fk=fk_object)
|
||||
m.save()
|
||||
m = self._refresh_if_needed(m)
|
||||
self.assertEqual(m.field, 3)
|
||||
|
||||
def test_generated_fields_can_be_deferred(self):
|
||||
fk_object = Foo.objects.create(a="abc", d=Decimal("12.34"))
|
||||
m = self.base_model.objects.create(a=1, b=2, fk=fk_object)
|
||||
m = self.base_model.objects.defer("field").get(id=m.id)
|
||||
self.assertEqual(m.get_deferred_fields(), {"field"})
|
||||
|
||||
def test_update(self):
|
||||
m = self.base_model.objects.create(a=1, b=2)
|
||||
self.base_model.objects.update(b=3)
|
||||
|
Loading…
Reference in New Issue
Block a user