I'm using hybrid_property, and would like the key of the property to be set 
to the attribute name, rather than the name of the getter. This is because 
I'm generating a getter function based on some args, rather than having the 
caller directly defining the getter. As a minimal example:

from __future__ import unicode_literals

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session


def prefixed_property(other_column, prefix):
    def instance_get(self):
        return prefix + getattr(self, other_column.key)

    return hybrid_property(fget=instance_get)


Base = declarative_base()

class Person(Base):
    __tablename__ = "person"

    id = Column(Integer, primary_key=True)
    name = Column(String)
    greeting = prefixed_property(name, "Hello ")


engine = create_engine("sqlite:///:memory:")

Base.metadata.create_all(engine)
session = Session(engine)

session.add(Person(name="Bob"))
session.commit()

assert session.query(Person.greeting).one() == ("Hello Bob", )
assert session.query(Person.greeting).one().greeting == "Hello Bob" # Fails 
with AttributeError since hybrid_property uses instance_get as the name

Is there a sensible way to do this? Or am I going about the problem the 
wrong way? In practice, I'm using this to define properties backed by a 
JSON field. In case it makes any different, here's the actual use-case I 
have:

from __future__ import unicode_literals

import os

from sqlalchemy import create_engine, Column, Integer
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.event import listens_for
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.pool import StaticPool


def json_property(json_column, name, type_=None):
    def instance_get(self):
        return getattr(self, json_column.key)[name]

    def instance_set(self, value):
        json_obj = getattr(self, json_column.key)
        if json_obj is None:
            setattr(self, json_column.key, {})
        getattr(self, json_column.key)[name] = value

    def cls_get(cls):
        expression = json_column[name]
        if type_:
            return expression.astext.cast(type_)
        else:
            return expression

    return hybrid_property(fget=instance_get, expr=cls_get, 
fset=instance_set)


Base = declarative_base()

class Person(Base):
    __tablename__ = "person"

    id = Column(Integer, primary_key=True)
    data = Column(JSONB, nullable=False)
    born = json_property(data, "born", Integer())


engine = create_engine(os.environ["TEST_DATABASE"], poolclass=StaticPool)
engine.execute("SET search_path TO pg_temp")

@listens_for(engine, "engine_connect")
def set_search_path(connection, branch):
    connection.execute("SET search_path TO pg_temp")


Base.metadata.create_all(engine)
session = Session(engine)

session.add(Person(born=1881))
session.commit()

assert session.query(Person.born).one() == (1881, ) # Works fine
assert session.query(Person.born).one().born == 1881 # Raises 
AttributeError since hybrid_property uses instance_get as the name

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to