The following fails with Django 2.2.6 but works with Django 1.11.x.
Did filter() of JSONfield change in 2.2.6 and the query needs to change, or could this be a bug?
Goal:
Select model rows where the related AbstractService.EntityJSON contents “Capability" list includes the value 'data.transfer.nonstriped'
Given: EntityJSON field contains "Capability": ["data.transfer.striped", "data.transfer.nonstriped"],
Executing:
objects = Endpoint.objects.filter(AbstractService__EntityJSON__Capability__contains=['data.transfer.nonstriped’])
serializernonstriped = xdinfo_gridftpn_Serializer(objects, many=True)
len(serializernonstriped.data)
Failes like this:
(Pdb) n
> /soft/python-pipenv/python-201910-zz_fwp56/lib/python3.7/site-packages/django/contrib/postgres/lookups.py(11)as_sql()
-> params = lhs_params + rhs_params
(Pdb) n
TypeError: can only concatenate tuple (not "list") to tuple
> /soft/python-pipenv/python-201910-zz_fwp56/lib/python3.7/site-packages/django/contrib/postgres/lookups.py(11)as_sql()
-> params = lhs_params + rhs_params
(Pdb) l
6
7 class PostgresSimpleLookup(Lookup):
8 def as_sql(self, qn, connection):
9 lhs, lhs_params = self.process_lhs(qn, connection)
10 rhs, rhs_params = self.process_rhs(qn, connection)
11 -> params = lhs_params + rhs_params
12 return '%s %s %s' % (lhs, self.operator, rhs), params
13
14
15 class DataContains(PostgresSimpleLookup):
16 lookup_name = 'contains'
(Pdb) lhs, lhs_params
('("glue2_db_abstractservice"."EntityJSON" -> %s)', ('Capability',))
(Pdb) rhs, rhs_params
('%s', [<django.contrib.postgres.fields.jsonb.JsonAdapter object at 0x107818f50>])
Models:
class AbstractGlue2EntityModel(models.Model):
ID = models.CharField(primary_key=True, max_length=200)
Name = models.CharField(max_length=128, null=True)
CreationTime = models.DateTimeField()
Validity = models.DurationField(null=True)
EntityJSON = JSONField()
class Meta:
abstract = True
db_name = 'glue2'
def __str__(self):
return str(self.ID)
class AbstractService(AbstractGlue2EntityModel):
ResourceID = models.CharField(db_index=True, max_length=40)
ServiceType = models.CharField(max_length=32)
Type = models.CharField(max_length=32)
QualityLevel = models.CharField(max_length=16, null=True)
class Endpoint(AbstractGlue2EntityModel):
ResourceID = models.CharField(db_index=True, max_length=40)
AbstractService = models.ForeignKey(AbstractService,
related_name='endpoints',
on_delete=models.CASCADE,
null=True)
HealthState = models.CharField(max_length=16)
ServingState = models.CharField(max_length=16)
URL = models.CharField(max_length=320)
QualityLevel = models.CharField(max_length=16, null=True)
InterfaceVersion = models.CharField(max_length=16)
InterfaceName = models.CharField(max_length=32)