juliotrigo/sqlalchemy-filters

Possible to pass value to hybrid_method?

Opened this issue · 0 comments

dcode commented

I've got a related model that provides a key/value extension of the main model and I'd like to be able to sort on the related model key/value. So, I want to say, "sort on the value field, if the key matches foo". I thought maybe I could use a hybrid method and pass the key to the method as shown below. I don't see anyway to pass that value to the hybrid method. I get the way the API is made, is there another way to accomplish this? If not, is can we add maybe an optional kwargs to the sort_spec that gets expanded if the sort field has the __call__ attribute? Another approach is maybe a sort of subquery?

class ImageProperty(db.Model):
    __tablename__ = "image_properties"

    id: Mapped[int] = mapped_column(primary_key=True)
    image_id: Mapped[str] = mapped_column(ForeignKey("images.id"))
    key: Mapped[str]
    value: Mapped[str]

    def __init__(self, key: str, value: str):
        self.key = key
        self.value = value

    @hybrid_method
    def value_for_key(self, key: str) -> str | None:
        if self.key == key:
            return self.value
        else:
            return None

class Image(ProxiedDictMixin, db.Model):
    __tablename__ = "images"

    id: Mapped[str] = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    properties: Mapped[dict[str, "ImageProperty"]] = relationship(
        collection_class=attribute_keyed_dict("key"), cascade="all, delete-orphan"
    )

Snippet to sort

if hasattr(Image, key):
    logger.debug("%s", {"model": "Image", "field": key, "direction": dir})
    sort_spec.append({"model": "Image", "field": key, "direction": dir})
else:
    logger.debug("%s", {"model": "ImageProperty", "field": key, "direction": dir})
    # TODO(dcode): This isn't right. need to sort on value when key == key
    sort_spec.append({"model": "ImageProperty", "field": value_for_key, "direction": dir})