Flask sqlalchemy добавить столбец во время запроса без результата кортежа - PullRequest
0 голосов
/ 28 марта 2020

Я работаю над проектом flask и застрял в проблеме, в которой я пытаюсь добавить оператор запроса в запрос в виде столбца.

Я перепробовал множество потенциальных решений, и самое близкое, что я нашел до сих пор, это add_columns(), проблема в том, что это заставляет запрос возвращать кортеж с объектом модели, который я запрашивал, и является результатом оператора case , что я хочу, это просто объект модели, в котором есть результат регистра.

Вот упрощенный код, который показывает мою проблему

from flask import Flask
from sqlalchemy.sql.expression import case
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///database.db"
db = SQLAlchemy(app)


class Image(db.Model):
    __tablename__ = 'images'

    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.Text)
    model_id = db.Column(db.Integer)


db.create_all()


@app.route('/')
def hello_world():
    image_ids = [1, 2, 3, 4, 5]
    image_weights = [0.1, 0.4, 0.23232, 0.21, 0.001]
    print(list(zip(image_ids, image_weights)))

    case_statement = case(
        [(uid == Image.id, weight) for uid, weight in zip(image_ids, image_weights)]
    )
    results = db.session.query(Image).add_columns(case_statement.label("weight")).filter(
        Image.id.in_(image_ids)).order_by("weight")
    print(results)
    print(results.all())
    return 'Hello World!'


if __name__ == '__main__':
    app.run(debug=True)

, вывод print(results.statement.compile(compile_kwargs={"literal_binds": True}))

SELECT images.id,
       images.url,
       images.model_id,
       CASE WHEN (images.id = 1) THEN 0.1 WHEN (images.id = 2) THEN 0.4 WHEN (images.id = 3) THEN 0.23232 WHEN (images.id = 4) THEN 0.21 WHEN (images.id = 5) THEN 0.001 END AS weight
  FROM images
 WHERE images.id IN (1, 2, 3, 4, 5) 
 ORDER BY weight;

вывод print(results.all())

[(<Image 5>, 0.001), (<Image 1>, 0.1), (<Image 4>, 0.21), (<Image 3>, 0.23232), (<Image 2>, 0.4)]

результат, который я ищу, это

[<Image 5>, <Image 1>, <Image 4>, <Image 3>, <Image 2>]

Одно простое решение для этого - просто go над каждым элементом в списке результатов и используйте setattr, чтобы установить вес атрибута объекта изображения для второго элемента в кортеже, но я не могу этого сделать, поскольку хочу создать функцию, которая возвращает объект запроса с фильтрами применяется не список объектов

1 Ответ

1 голос
/ 29 марта 2020

После поиска в документации sqlalchemy я нашел Время запроса SQL выражений в виде сопоставленных атрибутов

Эта доза - именно то, что мне нужно. Позволяет мне установить вес сопоставленного атрибута, который является результат оператора case.

изменения, которые я внес в свой код

class Image(db.Model):
    __tablename__ = 'images'

    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.Text)
    model_id = db.Column(db.Integer)

    weight = db.query_expression()
@app.route('/')
def hello_world():
    image_ids = [1, 2, 3, 4, 5]
    image_weights = [0.1, 0.4, 0.23232, 0.21, 0.001]

    case_statement = case([(uid == Image.id, weight) for uid, weight in zip(image_ids, image_weights)]).label("weight")
    results = db.session.query(Image).filter(Image.id.in_(image_ids)).options(
        db.with_expression(Image.weight, case_statement)).order_by(case_statement)
    print(results.statement.compile(compile_kwargs={"literal_binds": True}))
    for result in results:
        print(result, result.weight)
    return 'Hello World!'

results.all () теперь возвращает

[<Image 5>, <Image 1>, <Image 4>, <Image 3>, <Image 2>]

и каждый элемент в этот список теперь как атрибут с именем weight

Если есть лучший способ сделать это, пожалуйста, дайте мне знать, спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...