简体   繁体   English

Flask-SQLAlchemy-向查询添加新列以传递给模板

[英]Flask-SQLAlchemy - adding a new column to a query to pass to a template

For a simple library app in Flask with Flask-SQLAlchemy, I have a Book table and a Checkout table: 对于Flask中带有Flask-SQLAlchemy的简单图书馆应用,我有一个Book表和一个Checkout表:

class Checkout(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    checkout_date = db.Column(db.DateTime, nullable=False, default=func.now())
    return_date = db.Column(db.DateTime)

    book_id = db.Column(db.Integer, db.ForeignKey('book.id'))
    book = db.relationship('Book',
        backref=db.backref('checkout', lazy='dynamic'))

    def __repr__(self):
        return '<Checkout Book ID=%r from %s to %s>' % (self.book.id, self.checkout_date, self.return_date)

I want to keep all checkout records, and I figure the normalized way to do this is to use Checkout.return_date to determine if the book is returned or not. 我想保留所有结帐记录,并且我认为执行此操作的标准化方法是使用Checkout.return_date来确定是否退还该书。 If the return date of any associated Checkout record is null, the Book is still checked out and if it has no null records, the book is "available". 如果任何关联的Checkout记录的返回日期为空,则该书仍被检出,如果没有空记录,则该书为“可用”。 (Really it should never have two null return_dates) (真的,它永远不能有两个null return_dates)

The SQL for this view would be: 该视图的SQL为:

select book.*, min(checkout.return_date is not null) as available 
from book 
left join checkout 
on book.id = checkout.book_id
group by book.id;

I can't figure out how to do this in SQLAlchemy without copping out and using a raw SQL string: 我无法弄清楚如何在SQLAlchemy中做到这一点,而无需弄清楚并使用原始SQL字符串:

db.session.query(Book).from_statement('select book.*, min(checkout.return_date is not null) as available from book left join checkout on book.id = checkout.book_id group by book.id').all()

But I can't access spam_book.available : I get the error 'Book' object has no attribute 'available' 但是我无法访问spam_book.available :我收到错误'Book' object has no attribute 'available'

Is there a way to add a dynamic, temporary attribute on to a Book to pass to the template? 有没有一种方法可以在Book上添加动态的临时属性以传递给模板? Or is there a better way to go about doing this? 还是有更好的方法来做到这一点?

My end goal is to be able to do {% if book.available %} for each book, in the template. 我的最终目标是能够在模板中为每本书进行{% if book.available %}

From your description, I understand your Book to Checkout relationship is OneToMany and you are doing: 根据您的描述,我了解您的BookCheckout关系是OneToMany,并且您正在执行以下操作:

  • Only one book can be checked out for one record 只能签出一本书以取得一项记录
  • You library could have more than one copies of one book 您的图书馆可能有一本书不止一份
  • Different copies of one book will have different and unique book_id 一本书的不同副本将具有不同且唯一的book_id

Try to add a method for your Book model. 尝试为您的Book模型添加方法。

class Book(db.Model):
    # ...something you already have

    def is_available(self):
        return not self.checkout.filter(Checkout.return_date.isnot(None)).scalar()

In the template, just use: 在模板中,只需使用:

{% if book.is_available %}

should do the trick. 应该可以。

This is not tested as I don't have SQLAlchemy at hand. 这没有经过测试,因为我手头没有SQLAlchemy。 Please tell me if it does not work. 请告诉我它是否无效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM