﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
35438	Failed to insert an model instance into db that utilizes a UUID as its primary key and incorporates a GeneratedField.	长孙弘奕	nobody	"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."	Uncategorized	closed	Uncategorized	5.0	Normal	duplicate			Unreviewed	1	0	0	0	0	0
