Flask SQLAlchemy filter和filter_by不使用浮点值

2024-10-02 22:29:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Flask、Flask RESTful、Flask SQLAlchemy和MySQL编写API。问题是filter()filter_by根本不起作用

型号:

from app import db
from datetime import datetime

class AreaModel(db.Model):
    __tablename__ = 'aqi_records'

    id = db.Column(
        db.Integer,
        primary_key=True
    )
    aqi = db.Column(
        db.Integer,
        index=False,
        unique=False,
        nullable=False
    )
    latitude = db.Column(
        db.Float,
        index=False,
        unique=False,
        nullable=False
    )
    longitude = db.Column(
        db.Float,
        index=False,
        unique=False,
        nullable=False
    )
    created = db.Column(
        db.DateTime,
        index=False,
        unique=False,
        nullable=False,
        default=datetime.now()
    )

    def __repr__(self):
        return '<Area {}>'.format(self._string_coords())

    def _string_coords(self):
        return str(self.latitude) + '-' + str(self.longitude)

    def as_dict(self):
        r = {c.name: getattr(self, c.name) for c in self.__table__.columns}
        r['created'] = str(r['created'])
        return r

资源:

from flask_restful import Resource, request
from models import AreaModel

class AreaResource(Resource):
    def get(self):
        area_coords = request.args.get('area_coords')

        if not '-' in area_coords:
            return {'code': 400, 'message': 'Invalid coordinate format'}, 400

        latitude, longitude = area_coords.split('-')
        latitude, longitude = float(latitude), float(longitude)

        area = AreaModel.query.filter_by(latitude=latitude).first() # this is the line with the problem

        if not area:
            return {'code': 404, 'message': 'Area not found'}, 404

        return area.as_dict()

当我使用AreaModel.query.all()时,我得到表中的所有记录。但是如果我添加过滤器,我总是得到None结果,我不明白为什么

编辑1: 接收到的数据(coords)正确; 类型:浮子

编辑2: .get()也不起作用


Tags: fromimportselffalsedbindexreturncolumn
1条回答
网友
1楼 · 发布于 2024-10-02 22:29:48

浮点数很难使用,因为浮点数的文字表示可能与计算中使用的值或存储在数据库中的值不完全对应。在对this question的回答中对这种行为进行了深入讨论。MySQL中使用浮点进行查询的具体实例可以在herehere中找到

为了解决这个问题,MySQLdocs建议使用DECIMAL类型代替FLOATDOUBLE

在这个特定的例子中,我认为您可以选择使用DECIMAL(和Python Decimal类型)或字符串来表示纬度和经度

  • 如果您打算使用这些值执行数值计算,DECIMAL可能是更好的选择
  • 如果只查询精确的值,可以使用将值存储为字符串

下面是一个简短的示例,演示了如何使用浮点查询并不总是产生预期的结果:

import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import orm

Base = declarative_base()


class FloatTest(Base):
    __tablename__ = 'floattest'

    id = sa.Column(sa.Integer, primary_key=True)
    lat = sa.Column(sa.Float)

    def __repr__(self):
        return f'{self.__class__.__name__}(lat={self.lat})'


engine = sa.create_engine('mysql:///test', echo=True)
Base.metadata.drop_all(bind=engine, checkfirst=True)
Base.metadata.create_all(bind=engine)
Session = orm.sessionmaker(bind=engine)


floats = [1.5, 1.33, 1.625, 1.11, 1.34567]

session = Session()
for v in floats:
    session.add(FloatTest(lat=v))
session.commit()

for v in floats:
    res = session.query(FloatTest).filter(FloatTest.lat == v).first()
    print(v, res)
print()
session.close()

输出(删除SQL日志):

1.5 FloatTest(lat=1.5)
1.33 None
1.625 FloatTest(lat=1.625)
1.11 None
1.34567 None

相关问题 更多 >