Opened 6 years ago

Closed 5 years ago

Last modified 5 years ago

#29391 closed Bug (fixed)

Postgres array lookups need to call get_db_prep_value to adapt values to their db representation (FieldGetDbPrepValueMixin)

Reported by: Gavin Wahl Owned by: vinay karanam
Component: contrib.postgres Version: 2.0
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I have have a model that has an ArrayField of objects that need to be adapted to database values (EnumField from https://github.com/hzdg/django-enumfields).

The custom array lookups in django.contrib.postgres.arrays are not correctly calling the base fields get_db_prep_value/get_prep_value before passing the objects to the db api.

Repro:

import enum

from django.db import models
from django.contrib.postgres.fields import ArrayField


class TestEnum(enum.Enum):
    VALUE_1 = 'value_1'


class EnumField(models.CharField):
    def get_prep_value(self, value):
        if value is None:
            return None
        else:
            return value.value


class TestModel(models.Model):
    array_of_enums = ArrayField(EnumField(max_length=20))


TestModel.objects.filter(array_of_enums__contains=[TestEnum.VALUE_1])

Currently this fails with:

Traceback (most recent call last):
  File "django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: can't adapt type 'TestEnum'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "django/db/models/query.py", line 226, in __repr__
    data = list(self[:REPR_OUTPUT_SIZE + 1])
  File "django/db/models/query.py", line 250, in __iter__
    self._fetch_all()
  File "django/db/models/query.py", line 1118, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "django/db/models/query.py", line 53, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch)
  File "django/db/models/sql/compiler.py", line 899, in execute_sql
    raise original_exception
  File "django/db/models/sql/compiler.py", line 889, in execute_sql
    cursor.execute(sql, params)
  File "django/db/backends/utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: can't adapt type 'TestEnum'

I expect it to succeed and generate a WHERE clause of array_of_enums @> ARRAY['value_1'].

I think the fix is just to have the lookups inherit from FieldGetDbPrepValueMixin.

Change History (5)

comment:1 by Tim Graham, 6 years ago

Triage Stage: UnreviewedAccepted
Type: UncategorizedBug

comment:2 by vinay karanam, 5 years ago

Has patch: set
Owner: set to vinay karanam
Status: newassigned

comment:3 by Tim Graham <timograham@…>, 5 years ago

Resolution: fixed
Status: assignedclosed

In 5a36c81f:

Fixed #29391 -- Made PostgresSimpleLookup respect Field.get_db_prep_value().

comment:4 by Andrey Torsunov, 5 years ago

Which version of Django will have these changes? Thanks

comment:5 by Mariusz Felisiak, 5 years ago

3.0

Note: See TracTickets for help on using tickets.
Back to Top