I am attempting to use an @hybrid_property to order my parent table, and I have learnt that in order to do that, the @hybrid_property must be attached to a valid expression.
read - SQLAlchemy order by function result
@hybrid_property
def traffic(self):
# this getter is used when accessing the property of an instance
if self.traffic_summary and self.traffic_summary != []:
traffic = statistics.mean(
[st.page_views_per_million for st in self.traffic_summary]
)
if traffic == 0:
if self.traffic_history and self.traffic_history != []:
traffic = statistics.mean(
[st.page_views_per_million for st in self.traffic_history[:30]]
)
else:
if self.traffic_history and self.traffic_history != []:
traffic = statistics.mean(
[st.page_views_per_million for st in self.traffic_history[:30]]
)
else:
traffic = 0
return int(traffic)
@traffic.expression
def traffic(cls):
# this expression is used when querying the model
return case(
[(cls.traffic_summary != None), cls.traffic_history)],
else_=cls.traffic_summary
)
The @traffic.expression is the specific code, I want to modify, the issue is, I have absolutely no idea how to replicate statistics.mean([st.page_views_per_million for st in self.traffic_summary])
or the complicated Python logic in SQL.
My questions are twofold.
- how do I proceed to convert the above into SQL?
- is it even possible to convert such complex logic into SQL?
Updated with relationship models and the way the relationships are set up on the parent_table:
traffic_summary = db.relationship(
"traffic_summary", backref="traffic", passive_deletes=True, lazy="subquery"
)
traffic_by_country = db.relationship(
"traffic_by_country",
backref="store",
passive_deletes=True,
lazy="select",
order_by="desc(traffic_by_country.contribution_of_users)",
)
traffic_history = db.relationship(
"traffic_datapoint",
backref="traffic",
passive_deletes=True,
lazy="select",
order_by="desc(traffic_datapoint.date)",
)
class traffic_datapoint(ResourceMixin, db.Model):
id = db.Column(db.BigInteger, primary_key=True)
date = db.Column(db.DateTime)
page_views_per_million = db.Column(db.BigInteger)
page_views_per_user = db.Column(db.Float)
alexa_rank = db.Column(db.BigInteger)
reach_per_million = db.Column(db.BigInteger)
store_id = db.Column(
db.BigInteger,
db.ForeignKey(top_store.id, onupdate="CASCADE", ondelete="CASCADE"),
index=True,
nullable=True,
)
class traffic_by_country(ResourceMixin, db.Model):
id = db.Column(db.BigInteger, primary_key=True)
country_code = db.Column(db.String(30))
country_name = db.Column(db.String(100))
contribution_of_pageviews = db.Column(db.Float)
contribution_of_users = db.Column(db.Float)
store_id = db.Column(
db.BigInteger,
db.ForeignKey(top_store.id, onupdate="CASCADE", ondelete="CASCADE"),
index=True,
nullable=True,
)
class traffic_summary(ResourceMixin, db.Model):
id = db.Column(db.BigInteger, primary_key=True)
summary_type = db.Column(db.String(100))
alexa_rank = db.Column(db.BigInteger)
alexa_rank_delta = db.Column(db.BigInteger)
page_views_per_million = db.Column(db.BigInteger)
page_views_per_user = db.Column(db.Float)
reach_per_million = db.Column(db.BigInteger)
store_id = db.Column(
db.BigInteger,
db.ForeignKey(top_store.id, onupdate="CASCADE", ondelete="CASCADE"),
index=True,
nullable=True,
)