Opened 7 months ago
Closed 7 months ago
#36347 closed Bug (duplicate)
bulk_create and postgis geometry field error
| Reported by: | David Binetti | Owned by: | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 5.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I am trying to use bulk_create to create/update records on an existing model. One of the fields of this model is a nullable geometry field (PointField.). When I run the operation, I get an error that the geometry field is not properly formatted, although it is not one of the fields I'm updating. Sample model and query here:
class Person(models.Model):
id = HashidAutoField(
primary_key=True,
)
name = models.CharField(
max_length=100,
blank=False,
validators=[
MinLengthValidator(1),
]
)
external_id = models.IntegerField(
blank=False,
null=False,
)
geometry = models.PointField(
null=True,
blank=True,
)
def load_persons(rows):
person = Person(
[Person(**row) for row in rows],
update_conflicts=True,
update_fields=[
'name',
],
unique_fields=[
'external_id',
]
)
return persons
I then get the following error:
InternalError: parse error - invalid geometry
LINE 1: ...LL,NULL,NULL,NULL,NULL,NULL,NULL}')::tsvector[], ('{NULL,NUL...
^
HINT: "NU" <-- parse error at position 2 within geometry
full stacktrace:
---------------------------------------------------------------------------
InternalError_ Traceback (most recent call last)
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:105, in CursorWrapper._execute(self, sql, params, *ignored_wrapper_args)
104 else:
--> 105 return self.cursor.execute(sql, params)
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/psycopg/cursor.py:97, in Cursor.execute(self, query, params, prepare, binary)
96 except e._NO_TRACEBACK as ex:
---> 97 raise ex.with_traceback(None)
98 return self
InternalError_: parse error - invalid geometry
LINE 1: ...LL,NULL,NULL,NULL,NULL,NULL,NULL}')::tsvector[], ('{NULL,NUL...
^
HINT: "NU" <-- parse error at position 2 within geometry
The above exception was the direct cause of the following exception:
InternalError Traceback (most recent call last)
Cell In[7], line 1
----> 1 load_persons(rows)
File ~/repos/registrar/project/app/loaders.py:18, in load_persons(rows)
17 def load_persons(rows):
---> 18 persons = Person.objects.bulk_create(
19 [Person(**row) for row in rows],
20 update_conflicts=True,
21 update_fields=[
22 'last_name',
23 'first_name',
24 'middle_name',
25 'age',
26 'gender',
27 'registered',
28 'party',
29 'status',
30 'imported',
31 ],
32 unique_fields=[
33 'external_id',
34 ]
35 )
36 return persons
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/models/manager.py:87, in BaseManager._get_queryset_methods.<locals>.create_method.<locals>.manager_method(self, *args, **kwargs)
85 @wraps(method)
86 def manager_method(self, *args, **kwargs):
---> 87 return getattr(self.get_queryset(), name)(*args, **kwargs)
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/models/query.py:823, in QuerySet.bulk_create(self, objs, batch_size, ignore_conflicts, update_conflicts, update_fields, unique_fields)
821 if objs_without_pk:
822 fields = [f for f in fields if not isinstance(f, AutoField)]
--> 823 returned_columns = self._batched_insert(
824 objs_without_pk,
825 fields,
826 batch_size,
827 on_conflict=on_conflict,
828 update_fields=update_fields,
829 unique_fields=unique_fields,
830 )
831 connection = connections[self.db]
832 if (
833 connection.features.can_return_rows_from_bulk_insert
834 and on_conflict is None
835 ):
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/models/query.py:1882, in QuerySet._batched_insert(self, objs, fields, batch_size, on_conflict, update_fields, unique_fields)
1877 for item in [objs[i : i + batch_size] for i in range(0, len(objs), batch_size)]:
1878 if bulk_return and (
1879 on_conflict is None or on_conflict == OnConflict.UPDATE
1880 ):
1881 inserted_rows.extend(
-> 1882 self._insert(
1883 item,
1884 fields=fields,
1885 using=self.db,
1886 on_conflict=on_conflict,
1887 update_fields=update_fields,
1888 unique_fields=unique_fields,
1889 returning_fields=self.model._meta.db_returning_fields,
1890 )
1891 )
1892 else:
1893 self._insert(
1894 item,
1895 fields=fields,
(...) 1899 unique_fields=unique_fields,
1900 )
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/models/query.py:1854, in QuerySet._insert(self, objs, fields, returning_fields, raw, using, on_conflict, update_fields, unique_fields)
1847 query = sql.InsertQuery(
1848 self.model,
1849 on_conflict=on_conflict,
1850 update_fields=update_fields,
1851 unique_fields=unique_fields,
1852 )
1853 query.insert_values(fields, objs, raw=raw)
-> 1854 return query.get_compiler(using=using).execute_sql(returning_fields)
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/models/sql/compiler.py:1881, in SQLInsertCompiler.execute_sql(self, returning_fields)
1879 with self.connection.cursor() as cursor:
1880 for sql, params in self.as_sql():
-> 1881 cursor.execute(sql, params)
1882 if not self.returning_fields:
1883 return []
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:122, in CursorDebugWrapper.execute(self, sql, params)
120 def execute(self, sql, params=None):
121 with self.debug_sql(sql, params, use_last_executed_query=True):
--> 122 return super().execute(sql, params)
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/sentry_sdk/utils.py:1811, in ensure_integration_enabled.<locals>.patcher.<locals>.runner(*args, **kwargs)
1808 if sentry_sdk.get_client().get_integration(integration) is None:
1809 return original_function(*args, **kwargs)
-> 1811 return sentry_patched_function(*args, **kwargs)
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/sentry_sdk/integrations/django/__init__.py:651, in install_sql_hook.<locals>.execute(self, sql, params)
642 with record_sql_queries(
643 cursor=self.cursor,
644 query=sql,
(...) 648 span_origin=DjangoIntegration.origin_db,
649 ) as span:
650 _set_db_data(span, self)
--> 651 result = real_execute(self, sql, params)
653 with capture_internal_exceptions():
654 add_query_source(span)
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:79, in CursorWrapper.execute(self, sql, params)
78 def execute(self, sql, params=None):
---> 79 return self._execute_with_wrappers(
80 sql, params, many=False, executor=self._execute
81 )
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:92, in CursorWrapper._execute_with_wrappers(self, sql, params, many, executor)
90 for wrapper in reversed(self.db.execute_wrappers):
91 executor = functools.partial(wrapper, executor)
---> 92 return executor(sql, params, many, context)
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:100, in CursorWrapper._execute(self, sql, params, *ignored_wrapper_args)
98 warnings.warn(self.APPS_NOT_READY_WARNING_MSG, category=RuntimeWarning)
99 self.db.validate_no_broken_transaction()
--> 100 with self.db.wrap_database_errors:
101 if params is None:
102 # params default might be backend specific.
103 return self.cursor.execute(sql)
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/utils.py:91, in DatabaseErrorWrapper.__exit__(self, exc_type, exc_value, traceback)
89 if dj_exc_type not in (DataError, IntegrityError):
90 self.wrapper.errors_occurred = True
---> 91 raise dj_exc_value.with_traceback(traceback) from exc_value
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:105, in CursorWrapper._execute(self, sql, params, *ignored_wrapper_args)
103 return self.cursor.execute(sql)
104 else:
--> 105 return self.cursor.execute(sql, params)
File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/psycopg/cursor.py:97, in Cursor.execute(self, query, params, prepare, binary)
93 self._conn.wait(
94 self._execute_gen(query, params, prepare=prepare, binary=binary)
95 )
96 except e._NO_TRACEBACK as ex:
---> 97 raise ex.with_traceback(None)
98 return self
InternalError: parse error - invalid geometry
LINE 1: ...LL,NULL,NULL,NULL,NULL,NULL,NULL}')::tsvector[], ('{NULL,NUL...
^
HINT: "NU" <-- parse error at position 2 within geometry
Note:
See TracTickets
for help on using tickets.
Duplicate of #36289 (Postgres bulk_create error when geometry is null or a different SRID) fixed by d9bf0d07cc13c0351b65b025d7e8063864086975 in Django 5.2.1 meant to be
released on May 7th.