我正在尝试映射一个具有列的类,该类实际上并不存在,但它只是一个在查询时获取绑定参数的sql表达式。下面的模型是我正在尝试做的一个例子。
class House(db.Model):
__tablename__ = 'houses'
id = db.Column(db.Integer, primary_key=True)
@hybrid_property
def distance_from_current_location(self):
# what to return here?
return self.distance_from_current_location
@distance_from_current_location.expression
def distance_from_current_location(cls, latitude, longitude):
return db.func.earth_distance(
db.func.ll_to_earth(latitude, longitude), cls.earth_location)
# defer loading, as the raw value is pretty useless in python
earth_location = deferred(db.Column(EARTH))
然后我想通过flask-sqlalchemy查询:
latidude = 80.20393
longitude = -90.44380
paged_data = \
House.query \
.bindparams({'latitude': latitude, 'longitude': longitude}) \
.paginate(1, 20, False)
我的问题是:
bindparams
位,但它说明了我想要做的事情。是否可以这样做?我已经阅读了文档,但在示例中找不到任何带有bind参数的hybrid_property或方法......
(另外,因为这不是一个真正的专栏,而是我想在我的模型上使用的东西,我不希望这会触发alembic为它生成一个新列。)
谢谢!
答案 0 :(得分:0)
你不能这样做。 distance_from_current_location
也不是假列,因为它取决于查询特定的参数。想象一下,你要为此写一个SQL视图;你会怎么写这个定义? (提示:你不能。)
SQLAlchemy使用标识映射模式,这意味着对于特定主键,整个会话中只存在一个实例。您将如何处理查询相同的实例但具有不同的纬度/经度值? (从后面的查询返回的实例将覆盖从前一个查询返回的实例。)
执行此操作的正确方法是在查询时通过其他实体,如下所示:
House.query \
.with_entities(House, db.func.earth_distance(db.func.ll_to_earth(latitude, longitude), House.earth_location)) \
.filter(...)
或通过hyrbid_method
(其使用情况需要每次都传入latitude
和longitude
):
class House(db.Model):
...
@hybrid_method
def distance_from_current_location(self, latitude, longitude):
# implement db.func.ll_to_earth(latitude, longitude), self.earth_location) **in Python** here
@distance_from_current_location.expression
def distance_from_current_location(cls, latitude, longitude):
...