Как заставить объект Flask-SQLAlchemy загружать дочерние элементы отношений для шаблона Jinja?

StackOverflow https://stackoverflow.com//questions/22019567

Вопрос

У меня есть базовые модели для User и Post.В моей пользовательской модели у меня есть

posts = db.relationship('Post', backref='user', lazy='dynamic')

Однако, когда я делаю что-то вроде

return render_template('user.html', users=users)

Я хочу делать такие вещи, как

{% for user in users %}
    <tr>
        <td>{{ user.id }}</td>
        <td>{{ user.posts|length }}</td>
    </tr>
{% endfor %}

К сожалению, это не работает.Posts - это запрос, а не объект b/c из lazy='dynamic'.Я могу сделать вышеописанное, если изменю lazy='joined', но тогда он загружал бы все сообщения для пользователей в любое время, когда я запрашиваю пользователя.

Я попробовал добавить .options(joinedload('posts')) на мой запрос, но в нем говорилось, что

InvalidRequestError Недействительный запрос:'User.posts' не поддерживает заполнение объектов - быстрая загрузка не может быть применена.

Мы ценим любую помощь.

Это было полезно?

Решение

Просто снимите lazy="dynamic" аргумент, и вы сможете использовать joinedload без проблем.(Помните, что когда вы делаете это, вы подвергаете себя труднодиагностируемым проблемам с N+1 запросом.Если вам всегда будут нужны посты, используйте joined вместо этого).

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

class User(db.Model):
    posts = db.relationship('Post', backref='user')

class Post(db.Model):
    # etc.

User.posts_query = db.relationship(Post, lazy='dynamic')

Другие советы

Это объект запроса да, но у этих объектов запроса есть методы, которые могли бы вам помочь.Специально для этого варианта использования вы можете сделать:

{% for user in users %}
    <tr>
        <td>{{ user.id }}</td>
        <td>{{ user.posts.count() }}</td>
    </tr>
{% endfor %}

Вы должны выполнить .first() или .all() для вашего объекта запроса, чтобы получить фактический объект/ список.например,
users = User.query.all()

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top