#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.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018f56b747ec-b2a33923-b834-41c7-92ed-29d5c46232ff-000000%40eu-central-1.amazonses.com.

Reply via email to