无法在 SQLAlchemy 烧瓶中的结果对象上设置属性 [英] Can't set attribute on result objects in SQLAlchemy flask

查看:22
本文介绍了无法在 SQLAlchemy 烧瓶中的结果对象上设置属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 Flask-SQLAlchemy 时遇到问题,我可以在 place_collections 中设置对象的属性,但是当我想为 places 中的对象设置属性时,发生错误:

回溯(最近一次调用最后一次):文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py",第 2309 行,在 __call__ 中返回 self.wsgi_app(environ, start_response)文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/werkzeug/contrib/fixers.py",第 152 行,在 __call__返回 self.app(environ, start_response)wsgi_app 中的文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py",第 2295 行响应 = self.handle_exception(e)文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py",第 1741 行,在 handle_exception再加注(exc_type,exc_value,tb)文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/_compat.py",第 35 行,重新提出提升价值wsgi_app 中的文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py",第 2292 行响应 = self.full_dispatch_request()文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py",第 1815 行,在 full_dispatch_request 中rv = self.handle_user_exception(e)文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py",第 1718 行,在 handle_user_exception再加注(exc_type,exc_value,tb)文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/_compat.py",第 35 行,重新提出提升价值文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py",第 1813 行,在 full_dispatch_request 中rv = self.dispatch_request()文件/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py",第 1799 行,在 dispatch_request 中返回 self.view_functions[rule.endpoint](**req.view_args)文件/Users/user/Document/Python/Test/Code/app/main/views.py",第 108 行,在索引中place.distance = round(distance_computing, 1)属性错误:无法设置属性

如何设置加入搜索对象的属性,谁能帮帮我?

place_collections = Place.query.filter_by(county='BKK')地点 = db.session.query(Place.roll_number, Place.name, Place.website, Place.address, Place.distance).outerjoin(Rank, Rank.place_id == Place.place_id)

它们都是class 'flask_sqlalchemy.BaseQuery' 类型.

<小时>

 用于放置在 place_collections 中:distance_computing = Place.distance_calculator(float(place.lat), float(place.lng),数据['lat'], 数据['lng'])place.distance = round(distance_computing, 1)

<小时>

 用于放置地方:distance_computing = Place.distance_calculator(float(school.lat), float(school.lng),数据['lat'], 数据['lng'])place.distance = round(distance_computing, 1)

模型

class Rank(db.Model):__tablename__ = '排名'place_id = db.Column(db.String(50))名称 = db.Column(db.String(255), nullable=False,primary_key=True)等级 = db.Column(db.Integer)类地方(db.Model):_tablename_ = '学校'place_id = db.Column(db.String(50),primary_key=True)roll_number = db.Column(db.String(50))名称 = db.Column(db.String(255), nullable=False)地址 = db.Column(db.String(255))距离 = db.Column(db.String(50))rank = db.relationship('Rank',backref=db.backref('roll_number1'),lazy=True,uselist=False)

解决方案

place_collections = Place.query.filter_by(county='BKK') 将返回一个 Place 集合代码>对象.这类似于普通 SQLAlchemy 中的 session.query(Place).filter_by(county='BKK').

但是,来自 SQLAlchemy docs:

<块引用>

查询还接受 ORM 检测的描述符作为参数.任何时间多个类实体或基于列的实体表示为query() 函数的参数,返回结果表示为元组

关键点是,当您像此处所做的那样指定要查询的特定列时:

places = db.session.query(Place.roll_number, Place.name,Place.website, Place.address, Place.distance).外连接(等级,等级.place_id == Place.place_id)

结果表示为元组的集合.

我的第一印象是 can't set attribute 是一个奇怪的错误消息,因为尝试将属性值分配给 tuple,所以我尝试了它:

<预><代码>>>>t = 元组()>>>t. 属性 = 9回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中AttributeError: 'tuple' 对象没有属性 'attribute'

这不是您收到的错误消息.

所以我执行了一个类似于你的第二个查询的查询(模型只是我打开的一个项目中的一些东西):

<预><代码>>>>q = session.query(Racecard.id, Racecard.meeting)>>>a_result = q[0]>>>类型(a_result)<class 'sqlalchemy.util._collections.result'>

是的,所以我们没有得到元组,我们得到了一个 sqlalchemy.util._collections.result 对象.但是..

<预><代码>>>>issubclass(类型(a_result),元组)真的

因此,sqlalchemy.util._collections.result tuple类型.

如果我们尝试为不是查询列之一的属性赋值:

<预><代码>>>>a_result.newattribute = '东西'回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中AttributeError: 'result' 对象没有属性 'newattribute'

该错误消息与我们之前将属性分配给普通 tuple 时收到的错误消息非常相似.

那么为什么您会收到不同的错误消息?result 对象实际上更像是一个 namedtuple:

<预><代码>>>>从集合导入namedtuple>>>Racecard = namedtuple('Racecard', 'id, meeting')>>>rc = Racecard(1, 'Doomben')>>>rc.meeting = '鹰农场'回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中属性错误:无法设置属性

这与您收到的错误消息相同.

所以,sqlalchemy.util._collections.result 对象支持列名的属性访问,但由于它是一个 tuple 它仍然是不可变的,所以你不能写入这些属性.

要修复您的特定错误(除非您出于某种原因专门查询了那些列),请将您的 places 查询更改为:

places = db.session.query(Place).outerjoin(Rank, Rank.place_id == Place.place_id)

I encounter a problem with Flask-SQLAlchemy, I can set the attribute of the objects in place_collections, but when I want to set the attribute for objects in places, an error occurred:

Traceback (most recent call last):
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/werkzeug/contrib/fixers.py", line 152, in __call__
    return self.app(environ, start_response)
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
    response = self.handle_exception(e)
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/user/PycharmProjects/website/venv/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/user/Document/Python/Test/Code/app/main/views.py", line 108, in index
    place.distance = round(distance_computing, 1)
AttributeError: can't set attribute

How can I set the attribute for join search object, could anyone help me?

place_collections = Place.query.filter_by(county='BKK')

places = db.session.query(Place.roll_number, Place.name, Place.website, Place.address, Place.distance)
            .outerjoin(Rank, Rank.place_id == Place.place_id)

Both of them are class 'flask_sqlalchemy.BaseQuery' type.


for place in place_collections:
       distance_computing = Place.distance_calculator(float(place.lat), float(place.lng),
                                                            data['lat'], data['lng'])

       place.distance = round(distance_computing, 1)


for place in places:
       distance_computing = Place.distance_calculator(float(school.lat), float(school.lng),
                                                            data['lat'], data['lng'])

       place.distance = round(distance_computing, 1)

Model

class Rank(db.Model):
    __tablename__ = 'rank'
    place_id = db.Column(db.String(50))
    name = db.Column(db.String(255), nullable=False, primary_key=True)
    rank = db.Column(db.Integer)

class Place(db.Model):
    _tablename_ = 'school'
    place_id = db.Column(db.String(50), primary_key=True)
    roll_number = db.Column(db.String(50))
    name = db.Column(db.String(255), nullable=False)
    address = db.Column(db.String(255))
    distance = db.Column(db.String(50))
    rank = db.relationship('Rank',backref=db.backref('roll_number1'), lazy=True, uselist=False)

解决方案

place_collections = Place.query.filter_by(county='BKK') will return you a collection of Place objects. This is analogous to session.query(Place).filter_by(county='BKK') in plain vanilla SQLAlchemy.

However, from the SQLAlchemy docs:

The Query also accepts ORM-instrumented descriptors as arguments. Any time multiple class entities or column-based entities are expressed as arguments to the query() function, the return result is expressed as tuples

The key point being that when you specify specific columns to query as you have done here:

places = db.session.query(Place.roll_number, Place.name,
    Place.website, Place.address, Place.distance).
    outerjoin(Rank, Rank.place_id == Place.place_id)

the result is expressed as a collection of tuples.

My first impression was that can't set attribute was a strange error message to receive from trying to assign an attribute value to a tuple, so I tried it:

>>> t = tuple()
>>> t.attribute = 9
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'attribute'

That's not the error message that you received.

So I performed a query similar to your second one (the model is just something from a project that I had open):

>>> q = session.query(Racecard.id, Racecard.meeting)
>>> a_result = q[0]
>>> type(a_result)
<class 'sqlalchemy.util._collections.result'>

Right, so we aren't getting a tuple, we get a sqlalchemy.util._collections.result object. But..

>>> issubclass(type(a_result), tuple)
True

So, the sqlalchemy.util._collections.result is a type of tuple.

If we try to assign a value to an attribute that is not one of the columns that were queried:

>>> a_result.newattribute = 'something'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'result' object has no attribute 'newattribute'

That error message is very similar to the one that we got before when assigning an attribute to a plain tuple.

So why did you get a different error message? The result object is actually more like a namedtuple:

>>> from collections import namedtuple
>>> Racecard = namedtuple('Racecard', 'id, meeting')
>>> rc = Racecard(1, 'Doomben')
>>> rc.meeting = 'Eagle Farm'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

Which is the same error message that you are getting.

So, the sqlalchemy.util._collections.result object supports attribute access of the column names, but as it is a tuple it is still immutable, so you cannot write to those attributes.

To fix your specific error (unless there was some reason that you were specifically querying only those columns) change your places query to:

places = db.session.query(Place).outerjoin(Rank, Rank.place_id == Place.place_id)

这篇关于无法在 SQLAlchemy 烧瓶中的结果对象上设置属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆