[Django] #33373: Canont use expression as Right Hand Side of JSONField has_keys lookup

42 views
Skip to first unread message

Django

unread,
Dec 16, 2021, 5:09:06 PM12/16/21
to django-...@googlegroups.com
#33373: Canont use expression as Right Hand Side of JSONField has_keys lookup
-------------------------------------+-------------------------------------
Reporter: john- | Owner: nobody
parton |
Type: Bug | Status: new
Component: Database | Version: 3.2
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
I expected that the right hand side of the has_keys lookup for JSONField
could be any expression which returns an array of text, but it appears
that only python lists of strings are valid.

I think this is also an issue with 4.0, although I have only tested in on
3.2

Consider the following models.

{{{
class ProductVariant(models.Model):
product = models.ForeignKey(
'catalog.Product', on_delete=models.PROTECT
)

attributes = models.JSONField(_("Attributes"), default=dict)

class Product(models.Model):
configuration = ArrayField(
models.TextField()
)
}}}


Attempting to eval the queryset


{{{
ProductVariant.objects.filter(attributes__has_keys=F("product__configuration"))
}}}


results in


{{{
TypeError

'Col' object is not iterable
}}}


As a workaround, here's what I currently do


{{{
# Define the custom function
class HasAllKeys(Func):
function = None
template = '(%(expressions)s)'
arg_joiner = ' ?& '
arity = 2
output_field = BooleanField()

ProductVariant.objects.alias(
attributes_has_configuration_keys=HasAllKeys("attributes",
"product__configuration")
).filter(
attributes_has_configuration_keys=True
)
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/33373>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Dec 17, 2021, 1:13:19 AM12/17/21
to django-...@googlegroups.com
#33373: Support expressions on rhs for __has_keys, __has_any_keys JSONField
lookups.
-------------------------------------+-------------------------------------
Reporter: john-parton | Owner: nobody
Type: New feature | Status: closed
Component: Database layer | Version: 3.2
(models, ORM) |
Severity: Normal | Resolution: needsinfo
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* status: new => closed
* type: Bug => New feature
* resolution: => needsinfo


Comment:

Thanks for this ticket. Only `__has_keys` examples with lists are
[https://docs.djangoproject.com/en/stable/topics/db/queries/#has-keys
documented], so it's not a bug but a new feature. I'm skeptical, this can
be error-prone and tricky to implement for all backends (see
[https://github.com/django/django/pull/12392#issuecomment-624454015
discussion]). We can reconsider this decision if someone provides PoC with
cross-database compatibility.

--
Ticket URL: <https://code.djangoproject.com/ticket/33373#comment:1>

Django

unread,
Dec 17, 2021, 9:52:56 AM12/17/21
to django-...@googlegroups.com
#33373: Support expressions on rhs for __has_keys, __has_any_keys JSONField
lookups.
-------------------------------------+-------------------------------------
Reporter: john-parton | Owner: nobody
Type: New feature | Status: closed
Component: Database layer | Version: 3.2
(models, ORM) |
Severity: Normal | Resolution: needsinfo
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by john-parton):

Thanks for the feedback.

Examples in documentation aren't necessarily meant to be exhaustive.
Obviously it's impractical to give an example for every way a feature can
be use.

I do think it's a violation of expectations.

At the very least, I think it would be helpful to update the documentation
so that it notes that only iterables of strings are valid values for that
transformation.

It sounds like the ?& operator only works on Postgres, and not Oracle or
other database backends. Is that right?

Are we amenable to making it work with the Postgres backend, and
continuing to produce the current error for the other backends?

--
Ticket URL: <https://code.djangoproject.com/ticket/33373#comment:2>

Reply all
Reply to author
Forward
0 new messages