2014-11-09 2 views
0

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

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

@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_entriesfor петель ничего не меняет. Я также попытался добавить 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 
+0

Можете ли вы разместить свои модели SQLAlchemy? В частности, есть ли у вас отношения, определенные между «Книгой» и «Обложкой» (с backref)? Если это так, вы должны полностью удалить запрос 'cvr_entries' и изменить свой внутренний цикл' for' как нечто вроде '{% for cvr in entry.covers%}'. – jonafato

+0

В дополнение к моему предыдущему комментарию вы можете использовать ['joinload'] (http://docs.sqlalchemy.org/en/rel_0_9/orm/tutorial.html#joined-load), чтобы предотвратить ненужные запросы внутри цикла , – jonafato

+0

@jonafato Я попробовал 'cvr_entries = Cover.query.options (joinload (Cover.book))', но я получил 'NameError: глобальное имя 'joinload' не определен'. Я также попробовал подход 'entry.covers', но никаких записей не было возвращено вообще. – user2986242

ответ

2

Как правило, вы итерацию над model-- ваших отношений позволит вам сделать:

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, чтобы сделать его более похожим на естественный язык при доступе к модели.

Смежные вопросы