Запрос, возвращающий каждую обложку в БД для каждой записи?

Мой запрос, кажется, возвращает 1 запись для каждой обложки. То есть, если у меня в базе 3 обложки, то запрос вернет запись №1 трижды с каждой из разных обложек. Поскольку у меня есть 7 записей, я получаю 21 результат. Как мне структурировать запрос, чтобы вернуть обложку, связанную с записью?

Вот что у меня есть:

@app.route('/list', methods=['GET', 'POST'])
def list():
    entries = Book.query.order_by(Book.id.desc()).all()
    cvr_entries = Cover.query.filter(Cover.book).all()

    ### Other queries I've tried ###

    # cvr_entries = Cover.query.join(Cover.book).all()
    # cvr_entries = Cover.query.filter(Cover.book.any())
    # cvr_entries = Cover.query.filter(Cover.book.any()).all()

    return render_template(
        'list.html',
        entries=entries,
        cvr_entries=cvr_entries)

Вот страница вывода /list:

{% for entry in entries %}
{% for cvr in cvr_entries %}

<article class="entry">
    <img src="/static/data/covers/{{ cvr.name }}" alt="Cover for {{ entry.title }}" />
    <ul class="entry-info">
        <li class=""><h2>{{ entry.title }}</h2></li>
        <li class="">Summary: {{ entry.summary|truncate( 30, true ) }}</li>
    </ul>
</article>

{% endfor %}
{% endfor %}

Переключение порядка циклов entries и cvr_entries for ничего не меняет. Я также пытался добавить first() вместо all(), но это приводит к ошибке, где говорится

TypeError: 'Cover' object is not iterable

так что это был бюст. Я не понимаю, как построить запрос.

Вот моя модель по просьбе @jonafato:

book_to_cover = db.Table('book_to_cover',
    db.Column('cover_id', db.Integer, db.ForeignKey('cover.id')),
    db.Column('book_id', db.Integer, db.ForeignKey('book.id'))
)

class Book(db.Model):
    __tablename__ = 'book'

    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String())
    summary = db.Column(db.Text)

    book_to_cover = db.relationship('Cover', secondary=book_to_cover,
        backref=db.backref('book', lazy='dynamic'))

    def __repr__(self):
        return "<Book (title='%s')>" % (self.title)


class Cover(db.Model):
    __tablename__ = 'cover'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String())

    def __repr__(self):
        return "<Cover (name='%s')>" % self.name

person user2986242    schedule 09.11.2014    source источник
comment
Можете ли вы опубликовать свои модели SQLAlchemy? В частности, определена ли связь между Book и Cover (с обратной ссылкой)? Если это так, вы сможете полностью удалить запрос cvr_entries и изменить свой внутренний цикл for на что-то вроде {% for cvr in entry.covers %}.   -  person jonafato    schedule 09.11.2014
comment
В дополнение к моему предыдущему комментарию вы можете использовать joinedload для предотвращения ненужных запросов внутри цикла.   -  person jonafato    schedule 09.11.2014
comment
@jonafato Я пробовал cvr_entries = Cover.query.options(joinedload(Cover.book)), но получил NameError: global name 'joinedload' is not defined. Я также попробовал подход entry.covers, но записи вообще не возвращались.   -  person user2986242    schedule 09.11.2014
comment
Вы должны импортировать joinedload из sqlalchemy.orm, прежде чем сможете его использовать.   -  person dirn    schedule 09.11.2014
comment
Я импортировал его и получил ошибку InvalidRequestError: 'Cover.book' does not support object population - eager loading cannot be applied. Я нашел решение здесь, но это не сработало. Я также изменил свою загрузку с dynamic на joined безрезультатно.   -  person user2986242    schedule 09.11.2014


Ответы (1)


Как правило, вы перебираете модель — ваши отношения должны позволять вам делать следующее:

books = Book.query.all()
return render_template('list.html', books=books)

Затем в вашем шаблоне Jinja2 list.html:

{% for book in books %}
    <h3>{{ book }}</h3>
    <ul>
    {% for cover in book.book_to_cover %}
        <li>{{ cover }}</li>
    {% endfor %}
    </ul>
{% endfor %}

Было бы более естественно переименовать book_to_cover в covers, чтобы сделать его более похожим на естественный язык при доступе к модели.

person Doobeh    schedule 09.11.2014