1
0
mirror of https://github.com/django/django.git synced 2025-02-01 21:29:24 +00:00

Fixed #35024 -- Fixed model instance creation crash on GeneratedField.output_field with backend converters.

Regression in d9de74141e8a920940f1b91ed0a3ccb835b55729.

This is a long standing issue, however it caused a crash of
GeneratedFields for all output fields that have backend-specific
converters when the RETURNING clause is not supported
(MySQL and SQLite < 3.35).
That's why severity was exacerbated.
This commit is contained in:
Mariusz Felisiak 2023-12-07 20:50:18 +01:00 committed by GitHub
parent 2dca98f4f7
commit 5b3b791e90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 1 deletions

View File

@ -1819,6 +1819,7 @@ class SQLInsertCompiler(SQLCompiler):
)
opts = self.query.get_meta()
self.returning_fields = returning_fields
cols = []
with self.connection.cursor() as cursor:
for sql, params in self.as_sql():
cursor.execute(sql, params)
@ -1829,6 +1830,7 @@ class SQLInsertCompiler(SQLCompiler):
and len(self.query.objs) > 1
):
rows = self.connection.ops.fetch_returned_insert_rows(cursor)
cols = [field.get_col(opts.db_table) for field in self.returning_fields]
elif self.connection.features.can_return_columns_from_insert:
assert len(self.query.objs) == 1
rows = [
@ -1837,7 +1839,9 @@ class SQLInsertCompiler(SQLCompiler):
self.returning_params,
)
]
cols = [field.get_col(opts.db_table) for field in self.returning_fields]
else:
cols = [opts.pk.get_col(opts.db_table)]
rows = [
(
self.connection.ops.last_insert_id(
@ -1847,7 +1851,6 @@ class SQLInsertCompiler(SQLCompiler):
),
)
]
cols = [field.get_col(opts.db_table) for field in self.returning_fields]
converters = self.get_converters(cols)
if converters:
rows = list(self.apply_converters(rows, converters))

View File

@ -12,3 +12,7 @@ Bugfixes
* Reallowed, following a regression in Django 5.0, using a foreign key to a
model with a primary key that is not ``AutoField`` in
:attr:`.ModelAdmin.list_filter` (:ticket:`35020`).
* 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`).

View File

@ -482,6 +482,18 @@ class UUIDGrandchild(UUIDChild):
pass
class GeneratedModelFieldWithConverters(models.Model):
field = models.UUIDField()
field_copy = models.GeneratedField(
expression=F("field"),
output_field=models.UUIDField(),
db_persist=True,
)
class Meta:
required_db_features = {"supports_stored_generated_columns"}
class GeneratedModel(models.Model):
a = models.IntegerField()
b = models.IntegerField()

View File

@ -1,3 +1,5 @@
import uuid
from django.apps import apps
from django.db import IntegrityError, connection
from django.db.models import (
@ -14,6 +16,7 @@ from django.test.utils import isolate_apps
from .models import (
GeneratedModel,
GeneratedModelFieldWithConverters,
GeneratedModelNull,
GeneratedModelNullVirtual,
GeneratedModelOutputFieldDbCollation,
@ -266,6 +269,11 @@ class StoredGeneratedFieldTests(GeneratedFieldTestMixin, TestCase):
output_field_db_collation_model = GeneratedModelOutputFieldDbCollation
params_model = GeneratedModelParams
def test_create_field_with_db_converters(self):
obj = GeneratedModelFieldWithConverters.objects.create(field=uuid.uuid4())
obj = self._refresh_if_needed(obj)
self.assertEqual(obj.field, obj.field_copy)
@skipUnlessDBFeature("supports_virtual_generated_columns")
class VirtualGeneratedFieldTests(GeneratedFieldTestMixin, TestCase):