![](/img/trans.png)
[英]TypeError: sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7f86789f9bf8 is not JSON serializable
[英]TypeError: sqlalchemy properties -> class 'sqlalchemy.orm.attributes.InstrumentedAttribute'
我有以下sqlalchemy
類(簡化):
class Persons(Base):
__tablename__ = 'm_persons'
birthDate = db.Column(db.Date, nullable=True)
@hybrid_property
def age(self):
bd = self.birthDate
return relativedelta(date.today(), bd).years
@age.expression
def age(cls):
bd = cls.birthDate
return relativedelta(date.today(), bd).years
當我使用屬性將值打印為
person = Person.query.get(1)
print(person.age)
它可以正確打印人的年齡。 現在,當我嘗試將屬性用於查詢時:
Persons.query.filter(Persons.age >= min_age).all()
然后我得到以下錯誤:
TypeError: relativedelta only diffs datetime/date
我理解為cls.birthDate
是類型
class 'sqlalchemy.orm.attributes.InstrumentedAttribute'
那么問題是我缺少什么來獲取屬性birthDate
的價值?
當然,我一直在“搜索”並閱讀該文檔,但找不到它無法正常工作的原因或解決方案。
任何幫助,將不勝感激。
***編輯****錯誤的痕跡:
File "/Users/ext334/Dev/python/asocio/app/members/forms.py", line 174, in __init__
self.person.choices = listPersons(gender=subscription.gender, min_age=subscription.min_age, max_age=subscription.max_age)
File "/Users/ext334/Dev/python/asocio/app/members/forms.py", line 31, in listPersons
print(Persons.query.join(Members).filter(Persons.age >= min_age, Persons.age <= max_age, extract('year',Persons.birthDate) >= minBirthYear, extract('year',Persons.birthDate) <= maxBirthYear, Persons.sex == gender).order_by(Members.lastname, Members.firstname))
File "/Users/ext334/Dev/python/venv36/lib/python3.6/site-packages/sqlalchemy/ext/hybrid.py", line 867, in __get__
return self._expr_comparator(owner)
File "/Users/ext334/Dev/python/venv36/lib/python3.6/site-packages/sqlalchemy/ext/hybrid.py", line 1066, in expr_comparator
owner, self.__name__, self, comparator(owner),
File "/Users/ext334/Dev/python/venv36/lib/python3.6/site-packages/sqlalchemy/ext/hybrid.py", line 1055, in _expr
return ExprComparator(cls, expr(cls), self)
File "/Users/ext334/Dev/python/asocio/app/members/models.py", line 235, in age
return relativedelta(date.today(), cls.birthDate).years
File "/Users/ext334/Dev/python/venv36/lib/python3.6/site-packages/dateutil/relativedelta.py", line 102, in __init__
raise TypeError("relativedelta only diffs datetime/date")
TypeError: relativedelta only diffs datetime/date
完整查詢:
Persons.query.join(Members).filter(Persons.age >= min_age, Persons.age <= max_age, extract('year',Persons.birthDate) >= minBirthYear, extract('year',Persons.birthDate) <= maxBirthYear, Persons.sex == gender).order_by(Members.lastname, Members.firstname)
全班人:
class Persons(Base):
"""
Description of a person
"""
__tablename__ = 'm_persons'
user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE', onupdate='CASCADE'))
family_id = db.Column(db.Integer, db.ForeignKey('m_families.id', ondelete='CASCADE', onupdate='CASCADE'))
birthDate = db.Column(db.Date, nullable=True)
sex = db.Column(db.String(1), nullable=False, default='U') # U = unknown, F = Female, M = Male
# return the age in years, not rounded
@hybrid_property
def age(self):
return relativedelta(date.today(), self.birthDate).years
@age.expression
def age(cls):
return relativedelta(date.today(), cls.birthDate).years
好吧,我找到了解決方法,或者也許我更好地了解了它是如何工作的。 在@ age.expression中,您可以執行數據庫的功能。 所以我決定根據MySQL計算此@ age.expression中的年齡
這里的代碼:
@age.expression
def age(cls):
return func.year(func.from_days(func.to_days(date.today()) - func.to_days(cls.birthDate)))
基本上,這將計算出生日期到現在之間的年數。 所以flask-sqlalchemy查詢是
Persons.query.join(Members).filter(Persons.age >= min_age, Persons.age <= max_age, extract('year',Persons.birthDate) >= minBirthYear, extract('year',Persons.birthDate) <= maxBirthYear, Persons.sex == gender).order_by(Members.lastname, Members.firstname)
生成的sql語句為:
SELECT m_persons.id AS m_persons_id, m_persons.date_created AS m_persons_date_created, m_persons.date_modified AS m_persons_date_modified, m_persons.user_id AS m_persons_user_id, m_persons.family_id AS m_persons_family_id, m_persons.`birthDate` AS `m_persons_birthDate`, m_persons.sex AS m_persons_sex FROM m_persons INNER JOIN users ON users.id = m_persons.user_id WHERE year(from_days(to_days(%s) - to_days(m_persons.`birthDate`))) >= %s AND year(from_days(to_days(%s) - to_days(m_persons.`birthDate`))) <= %s AND EXTRACT(year FROM m_persons.`birthDate`) >= %s AND EXTRACT(year FROM m_persons.`birthDate`) <= %s AND m_persons.sex = %s ORDER BY users.lastname, users.firstname
因此@ age.expression會返回year(from_days(to_days(%s) - to_days(m_persons.birthDate)))
作為總結,我想說的是,在@ age.expression中,您只能應用數據庫功能,而不能真正對列本身進行操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.