Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#33373 closed New feature (needsinfo)

Support expressions on rhs for __has_keys, __has_any_keys JSONField lookups.

Reported by: john-parton Owned by: nobody
Component: Database layer (models, ORM) Version: 3.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 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
)

Change History (2)

comment:1 by Mariusz Felisiak, 3 years ago

Resolution: needsinfo
Status: newclosed
Summary: Canont use expression as Right Hand Side of JSONField has_keys lookupSupport expressions on rhs for __has_keys, __has_any_keys JSONField lookups.
Type: BugNew feature

Thanks for this ticket. Only __has_keys examples with lists are 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 discussion). We can reconsider this decision if someone provides PoC with cross-database compatibility.

comment:2 by john-parton, 3 years ago

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?

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