SQLAlchemy AttributeError: 'Attribute' object has no attribute 'translation'
Condition
The user makes a purchase and it is stored as a transaction in 3 different tables (depending on the type). I need to calculate the total transactions/purchases of male and female users, so I need to see all 3 tables.
For this, I created one @property
in the User table :
@property
def count_credits_purchases(self):
trans = object_session(self).query(Transaction_1).filter(Transaction_1.type == "credits").with_parent(self).count()
trans_vk = object_session(self).query(Transaction_2).filter(Transaction_2.type == "credits").with_parent(self).count()
trans_stripe = object_session(self).query(Transaction_3).filter(Transaction_3.type == "credits").with_parent(self).count()
value = trans + trans_vk + trans_stripe
return int(value)
I am trying to calculate the total amount of purchases using sqlalchemy func.sum()
:
total_purchases_males_credits = db_session.query(func.sum(Users.count_credits_purchases))
.filter(Users.date_added >= start_date, Users.date_added <= end_date, Users.gender == "1")
.scalar()
question
AttributeError: 'property' object has no attribute 'translate'
The pan method is a string method, what's going on here? I definitely return an integer count_credits_purchases
in .
I tested and checked that the value is always correct for each user:
all_users = db_session.query(Users).limit(200)
for user in all_users:
print (user.count_credits_purchases) # gives correct result
I can create a variable and do the calculation in a loop, but it's horribly inefficient and could take 1 hour if there are 50k users. I need to know how to use the @property
property
The best solution is probably to use @hybrid_property
.
I came up with a completely different solution using the classic approach. This is very fast and I don't see any downsides so far:
# Normal method to calculate | Best case would probably be @hybrid_method
def count_credits_purchases(self, start_date, end_date, gender):
trans = db_session.query(Transaction_1).filter(Transaction_1.type == "credits", Transaction_1.user_id == Users.id).filter(Users.date_added >= start_date, Users.date_added <= end_date, Users.gender == gender).count()
trans_vk = db_session.query(Transaction_2).filter(Transaction_2.type == "credits", Transaction_2.user_id == Users.id).filter(Users.date_added >= start_date, Users.date_added <= end_date, Users.gender == gender).count()
trans_stripe = db_session.query(Transaction_3).filter(Transaction_3.type == "credits", Transaction_3.user_id == Users.id).filter(Users.date_added >= start_date, Users.date_added <= end_date, Users.gender == gender).count()
value = trans + trans_vk + trans_stripe
return value
Call python:
total_purchases_males_credits = Users().count_credits_purchases(start_date, end_date, "1")
I'm still wondering how good is this approach compared to hybrid_property?
edit:
It is also possible to use @hybrid_method
:
@hybrid_method
def count_credits_purchases(self, start_date, end_date, gender):
trans = db_session.query(Transaction_1).filter(Transaction_1.type == "credits", Transaction_1.user_id == Users.id).filter(Users.date_added >= start_date, Users.date_added <= end_date, Users.gender == gender).count()
trans_vk = db_session.query(Transaction_2).filter(Transaction_2.type == "credits", Transaction_2.user_id == Users.id).filter(Users.date_added >= start_date, Users.date_added <= end_date, Users.gender == gender).count()
trans_stripe = db_session.query(Transaction_3).filter(Transaction_3.type == "credits", Transaction_3.user_id == Users.id).filter(Users.date_added >= start_date, Users.date_added <= end_date, Users.gender == gender).count()
value = trans + trans_vk + trans_stripe
return value
and use it:
total_purchases_males_credits = db_session.query(func.sum(Users.count_credits_purchases(start_date, end_date, "1"))).scalar()