[Django] #35438: Failed to insert an model instance into db that utilizes a UUID as its primary key and incorporates a GeneratedField.

7 views
Skip to first unread message

Django

unread,
May 8, 2024, 1:40:07 AMMay 8
to django-...@googlegroups.com
#35438: Failed to insert an model instance into db that utilizes a UUID as its
primary key and incorporates a GeneratedField.
-----------------------------------------+------------------------
Reporter: 长孙弘奕 | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 5.0
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 1
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
I have defined a model that employs a UUIDField as its primary key,
accompanied by a JSONField and several GeneratedFields, which are intended
for indexing the JSONFields. However, when attempting to load data via
loaddata from a JSON fixture, the process fails during the execution of
the execute_sql method within django/db/models/SQL/compiler.py. The
problematic code snippet is as follows:

{{{
def execute_sql(self, returning_fields=None):
....
if not self.returning_fields:
return []
....
else:
cols = [opts.pk.get_col(opts.db_table)]
rows = [
(
self.connection.ops.last_insert_id(
cursor,
opts.db_table,
opts.pk.column,
),
)
]
converters = self.get_converters(cols)
if converters:
rows = list(self.apply_converters(rows, converters))
return rows
}}}


Here, returning_fields comprises GeneratedFields, thereby preventing the
method from directly returning an empty list at the outset of its logical
execution. Moreover, since the model's primary key is not an
AUTO_INCREMENT column (it's a UUID), last_insert_id() erroneously returns
0. This subsequently triggers an error within self.apply_converters(rows,
converters) as it attempts to treat 0 as a UUID.

To address this issue, the else block logic requires adjustment to
accommodate the presence of GeneratedField. Alternatively, within
django/db/models/base.py's _save_table method, one could exclude
GeneratedField from returning_fields. A modified approach might resemble:


{{{
#Original: returning_fields = meta.db_returning_fields
returning_fields = [ f for f in meta.db_returning_fields if
not f.generated]
results = self._do_insert(
cls._base_manager, using, fields, returning_fields, raw
)
if results:
for value, field in zip(results[0], returning_fields):
setattr(self, field.attname, value)
return updated
}}}

This adjusted strategy has proven effective in my project, successfully
circumventing the aforementioned issues without introducing new problems.
--
Ticket URL: <https://code.djangoproject.com/ticket/35438>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
May 8, 2024, 4:11:43 AMMay 8
to django-...@googlegroups.com
#35438: Failed to insert an model instance into db that utilizes a UUID as its
primary key and incorporates a GeneratedField.
-------------------------------+--------------------------------------
Reporter: 长孙弘奕 | Owner: nobody
Type: Uncategorized | Status: closed
Component: Uncategorized | Version: 5.0
Severity: Normal | Resolution: needsinfo
Keywords: | Triage Stage: Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Changes (by Sarah Boyce):

* resolution: => needsinfo
* status: new => closed

Comment:

Hi 长孙弘奕, thank you for the report and patch.
I'm struggling to see exactly what is happening here. Can you perhaps
share your model, fixture and error?
If you provide a regression test to the patch that will also be really
helpful to be able to see the issue
--
Ticket URL: <https://code.djangoproject.com/ticket/35438#comment:1>
Reply all
Reply to author
Forward
0 new messages