简体   繁体   English

TypeError:sqlalchemy属性->类'sqlalchemy.orm.attributes.InstrumentedAttribute'

[英]TypeError: sqlalchemy properties -> class 'sqlalchemy.orm.attributes.InstrumentedAttribute'

I have the following sqlalchemy class (simplified): 我有以下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

when I use the property to print the value as 当我使用属性将值打印为

person = Person.query.get(1)
print(person.age)

It correctly prints the age of the person. 它可以正确打印人的年龄。 Now when I try to use the property into a query like: 现在,当我尝试将属性用于查询时:

Persons.query.filter(Persons.age >= min_age).all()

Then I got the following error : 然后我得到以下错误:

TypeError: relativedelta only diffs datetime/date

Which I understand as cls.birthDate is of type 我理解为cls.birthDate是类型

class 'sqlalchemy.orm.attributes.InstrumentedAttribute'

So the question what I am missing to get the value of the property birthDate ? 那么问题是我缺少什么来获取属性birthDate的价值?

Of course I have been 'googleing' around and read the doc but could not find the reason why it is not working or a solution. 当然,我一直在“搜索”并阅读该文档,但找不到它无法正常工作的原因或解决方案。

Any help would be appreciated. 任何帮助,将不胜感激。

*** EDIT **** The trace of the error : ***编辑****错误的痕迹:

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

The full query : 完整查询:

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)

The full class Persons : 全班人:

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

Well I found a workaround or maybe I better understood how it worked. 好吧,我找到了解决方法,或者也许我更好地了解了它是如何工作的。 In @age.expression you can execute the functions of your database. @ age.expression中,您可以执行数据库的功能。 So I decided to calculate the age inside this @age.expression based on the MySQL 所以我决定根据MySQL计算此@ age.expression中的年龄

Here the code : 这里的代码:

@age.expression
def age(cls):
    return func.year(func.from_days(func.to_days(date.today()) - func.to_days(cls.birthDate)))

Basically, this calculate the number of years between the birthdate and now. 基本上,这将计算出生日期到现在之间的年数。 So the flask-sqlalchemy query is 所以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)

The generated sql statement is: 生成的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

and thus the @age.expression returns year(from_days(to_days(%s) - to_days(m_persons.birthDate))) which is well understood in the query 因此@ age.expression会返回year(from_days(to_days(%s) - to_days(m_persons.birthDate)))

As a summary I would say that in the @age.expression you can only applied database function and not really operate on the column itself. 作为总结,我想说的是,在@ age.expression中,您只能应用数据库功能,而不能真正对列本身进行操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 TypeError:位于0x7f86789f9bf8的sqlalchemy.orm.attributes.InstrumentedAttribute对象不是JSON可序列化的 - TypeError: sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7f86789f9bf8 is not JSON serializable 获取 SQLalchemy 检测属性的值 - Fetch a value of SQLalchemy instrumentedattribute SQLAlchemy,InstrumentedAttribute,列,属性 - SQLAlchemy, InstrumentedAttribute, Column, Attribute 使用SQLAlchemy检索ORM属性 - Retrieving ORM properties with SQLAlchemy 如何将SQLAlchemy与类属性(和属性)一起使用? - How to use SQLAlchemy with class attributes (and properties)? SQLAlchemy ORM-将两个类属性添加到单个表 - SQLAlchemy ORM - adding two class attributes to a single table sqlalchemy.orm.exc.UnmappedInstanceError: Class 'builtins.TypeError' 未映射 - sqlalchemy.orm.exc.UnmappedInstanceError: Class 'builtins.TypeError' is not mapped 如何判断InstrumentedAttribute是否是sqlalchemy中的关系? - How to tell if a InstrumentedAttribute is a relation in sqlalchemy? 如何在查询之前设置SQLAlchemy ORM类的属性? - How do I set the attributes of a SQLAlchemy ORM class before query? 当sqlalchemy ORM类属性与数据库列不同时,如何获取ORM类属性的列表? - When the sqlalchemy ORM class attributes are different from database columns, how to get a list of the ORM class attributes?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM