#30711: Add HStoreF for F object like querying on HStoreField.
-------------------------------------+-------------------------------------
               Reporter:  tiptop96   |          Owner:  (none)
                   Type:  New        |         Status:  new
  feature                            |
              Component:             |        Version:  2.2
  contrib.postgres                   |
               Severity:  Normal     |       Keywords:  HStoreField F
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 When using F objects for key lookups on HStoreFields it never digs down to
 get the keys but unexpectedly returns the entire object.

 Lets say we have this model:
 {{{
 from django.contrib.postgres.fields import HStoreField
 from django.db import models

 class Person(models.Model):
     name = models.CharField(max_length=256)
     attributes = HStoreField()
 }}}

 We then populate it.
 {{{
 Person.objects.create(name="James", attributes={"age": "30", "height":
 "190"})
 }}}

 Here comes the thing that bothers me. If we try to access either of these
 keys the entire attributes cell will be returned.
 {{{
 p = Person.objects.annotate(length=F("attributes__height"))
 p[0].height
 >>> {"age": "30", "height": "190"}
 }}}

 While the expected result would be an error or the value of the height
 field, it's not.

 I propose either making F objects support these fields or creating a new
 type to handle this, a workaround that I'm playing around with myself.

 {{{
 from django.contrib.postgres.fields.jsonb import KeyTransformFactory

 class HStoreF(F):
     def resolve_expression(self, query=None, allow_joins=True, reuse=None,
 summarize=False, for_save=False):
         rhs = super().resolve_expression(query, allow_joins, reuse,
 summarize, for_save)
         field_list = self.name.split("__")
         if field_list[-1] == rhs.target.name:
             raise LookupError(
             "HStoreF requires a key lookup in order to avoid unexpected
 behavior. "
             "Please append '__somekey' to '{}'."
             .format("__".join(field_list)))
         return KeyTransformFactory(field_list[-1])(rhs)

 }}}

 An issue with this is that updating models with it still wont work. As an
 error is raised in {{{Query.resolve_ref()}}} due to the fact that it
 interprets the {{{"__"}}} as an attempted join. This could be solved by
 using a different lookup separator for keys (maybe relevant for JSONField
 to?), but I was unable to successfully implement this.

 Similar issue with JSONField: https://code.djangoproject.com/ticket/29769

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

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/051.fe579ab93d5dbcefd98faddf3e89c416%40djangoproject.com.

Reply via email to