#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 django-updates+unsubscr...@googlegroups.com.
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