Flask SQLAlchemy запрос с order_by возвращает ошибку, нет такого столбца - PullRequest
0 голосов
/ 18 февраля 2020

Вот мои модели:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)
db = SQLAlchemy(app)


class Person(db.Model):
    __tablename__ = 'persons'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False, unique=True)
    pets = db.relationship('Pet', backref='owner', lazy='dynamic')

    def __init__(self, *args, **kwargs):
        super(Person, self).__init__(*args, **kwargs)

    def __repr__(self):
        return f'<Person id:{self.id} name:{self.name}>'

class Pet(db.Model):
    __tablename__ = 'pets'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False, unique=True)
    owner_id = db.Column(db.Integer, db.ForeignKey('persons.id'), nullable=False)

    def __init__(self, *args, **kwargs):
        super(Pet, self).__init__(*args, **kwargs)

    def __repr__(self):
        return f'<Pet id:{self.id} name:{self.name} owner_id:{self.owner_id}>'

Я пытаюсь получить список людей, упорядоченных по количеству домашних животных с этим запросом:

persons = Person.query.order_by(Person.pets).all()

И получаю эту ошибку:

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: pets.owner_id
[SQL: SELECT persons.id AS persons_id, persons.name AS persons_name
FROM persons ORDER BY persons.id = pets.owner_id]

Что я делаю не так? У меня есть предположение, что мне нужно сделать запрос с помощью join (), но исследования в Google не дали рабочих решений.

1 Ответ

0 голосов
/ 19 февраля 2020

Если вы осмотрите SQL, вы заметите, что элемента FROM pets нет, поэтому ORDER BY persons.id = pets.owner_id не выполняется. Это происходит потому, что атрибут отношения Person.pets отображается как его предложение ON в контексте запроса или, другими словами, как persons.id = pets.owner_id. Есть много способов сформировать правильный запрос, например, используя JOIN и GROUP BY:

Person.query.\
    outerjoin(Person.pets).\
    group_by(Person.id).\
    order_by(func.count(Pet.id)).\
    all()

LEFT OUTER JOIN гарантирует, что люди без домашних животных также будут рассматриваться.

...